Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.149.233.62] |
|
Сообщ.
#1
,
|
|
|
Всем привет.
В общем - надо сделать вот так вот: class TestTimer { public: TestTimer() { auto callback = [&](PVOID pvContext, BOOLEAN fTimeout) { std::cout << "Ky ky member: " << ++m_member; }; CreateTimerQueueTimer(&m_hTimer, NULL, callback, NULL, 10000, 5 * 1000, 0); } ~TestTimer() { DeleteTimerQueueTimer(NULL, m_hTimer, NULL); } private: HANDLE m_hTimer; int m_member; }; int main() { TestTimer timer_quard; std::cin.get(); } Но так не работает. Если убрать из списка захвата ссылку - все норм конвертируется. Как я понимаю без списка захвата конвертируется норм по стандарту? А если мне надо со списком захвата, то как? |
Сообщ.
#2
,
|
|
|
Цитата KILLER @ А если мне надо со списком захвата, то как? Никак. Лямбды со списком захвата не кастуются к указателям на функцию. У CreateTimerQueueTimer есть параметр: Parameter [in, optional] A single parameter value that will be passed to the callback function. Использую его. |
Сообщ.
#3
,
|
|
|
Т.е. если убрать ссылку из списка захвата - все компилируется и работает просто супер пупер. А со списком никак ((
Добавлено Цитата XandoX @ Никак. Лямбды со списком захвата не кастуются к указателям на функцию. Вообще никак не кастуются? Может как то через std::function можно такое провернуть? |
Сообщ.
#4
,
|
|
|
Цитата KILLER @ Вообще никак не кастуются? Может как то через std::function можно такое провернуть? Нет. Через std::function тоже не получиться. Почему так происходить, можно понять из того как что лямбды на самом деле это локально сгенерированные классы с operator(). Для лябмды с со списком захвата, нужно иметь контекст, который неявно передается через this, для лямбд без списка захвата, this не нужен и operator() вообще может быть статическим. И вот указатель на статический operator() и передается как указатель на функцию. Это вообще конечно все достаточно вольное объяснение, но все примерно так и работает. |
Сообщ.
#5
,
|
|
|
Ясно, это пичально блин, придется структуру заводить, потому как мне там на самом деле не один мембер надо передавать, думал отделаться парой строчек. Ну ладно тогдаЮ буду через параметр таймера передавать.
Спасибо. |
Сообщ.
#6
,
|
|
|
Цитата KILLER @ Ну а кто не даёт сделать типа того:Ясно, это пичально блин, придется структуру заводить, потому как мне там на самом деле не один мембер надо передавать, думал отделаться парой строчек. class TestTimer { public: TestTimer() { auto callback = [](PVOID pvContext, BOOLEAN fTimeout) { std::cout << "Ky ky member: " << ++reinterpret_cast<TestTimer*>(pvContext)->m_member; }; CreateTimerQueueTimer(&m_hTimer, NULL, callback, this, 10000, 5 * 1000, 0); } ~TestTimer() { DeleteTimerQueueTimer(NULL, m_hTimer, NULL); } private: HANDLE m_hTimer; int m_member; }; |
Сообщ.
#7
,
|
|
|
Цитата Qraizer @ Ну а кто не даёт сделать типа того: Я примерно так и сделал, только пришлось делать и передавать кортеж. Я хз на сколько это верный подход. У меня получается вот этот класс TestTimer содержит приватные поля: 1) мьютекс, который нужно передать в нутрь лямбды, 2) мапу объектов, которая тоже закрытая и которую тоже надо передать в лямбду. В итоге получилось что то типа того: class TestTimer { public: TestTimer() : m_member1(10), m_member2(20) { m_Tuple = std::make_tuple(&m_member1, &m_member2, this); auto callback = [](PVOID pvContext, BOOLEAN fTimeout) { using TTupleArgs = std::tuple<int*, int*, TestTimer*>; TTupleArgs args = *((TTupleArgs*)(pvContext)); int& arg1 = *std::get<0>(args); int& arg2 = *std::get<1>(args); TestTimer* arg3= std::get<2>(args); std::cout << "Arg1: " << arg1 << " Arg2: " << arg2 << std::endl; arg3->print(); ++arg1; ++arg2; }; CreateTimerQueueTimer(&m_hTimer, NULL, callback, &m_Tuple, 1000, 5 * 1000, 0); } void print() { std::cout << "Yo yo1: " << m_member1 << " Yo yo2: " << m_member2 << std::endl; } ~TestTimer() { DeleteTimerQueueTimer(NULL, m_hTimer, NULL); } private: HANDLE m_hTimer; int m_member1; //! на самом деле Mutex int m_member2; //! На самом деле какой нибудь std::map<std::string, SomeObject> std::tuple<int*, int*, TestTimer*> m_Tuple; }; Или в принципе такое имеет право на жизнь? Мне кажется как то всеравно громоздко вышло? Может как то проще сделать можно? |
Сообщ.
#8
,
|
|
|
Ты можешь разделить callback от таймера и имплементацию callback-а
будет красивше, ИМХО (Ну я исхожу еще из своего правила, что лямбда длиннее 3 строк, что-то неправильное) class TestTimer { public: TestTimer() : m_member1(10), m_member2(20) { auto callback = [](PVOID pvContext, BOOLEAN fTimeout) { reinterpret_cast<TestTimer*>(pvContext)->timerCallbackHandler(); }; CreateTimerQueueTimer(&m_hTimer, NULL, callback, this, 1000, 5 * 1000, 0); } void print() { std::cout << "Yo yo1: " << m_member1 << " Yo yo2: " << m_member2 << std::endl; } ~TestTimer() { DeleteTimerQueueTimer(NULL, m_hTimer, NULL); } private: void timerCallbackHandler() { std::cout << "m_member1: " << m_member1 << " m_member2: " << m_member2 << std::endl; print(); ++m_member1; ++m_member2; } private: HANDLE m_hTimer; int m_member1; //! на самом деле Mutex int m_member2; //! На самом деле какой нибудь std::map<std::string, SomeObject> std::tuple<int*, int*, TestTimer*> m_Tuple; }; |
Сообщ.
#9
,
|
|
|
Да, кстати так лучше. Что то я об этом даже не подумал, с какими то кортежами извращался тут. Спасибо.
|