Используйте Lambda с состоянием в качестве параметра указателя функции

Я пытаюсь использовать лямбду с состоянием в качестве параметра указателя функции, здесь состояние означает, что оно захватывает из своего контекста. В соответствии с этой проблемой это незаконно: Почему неявное преобразование лямбда-функции в указатель на функцию запрещает захват статических членов по ссылке?

Текущая функция, в которую я хочу передать лямбду: void foo( void( func* )( unsigned long ) )

Это упрощенная версия того, где я создаю лямбду, которую хочу передать:

void MyClass::myClassFunc( int a, int b, int c )
{
    auto myLambda = [&]( unsigned long val ){ a+=val;b+=val;c+=val; };
    foo( /*some magic conversion*/ myLambda );
}

Простое решение, перегрузка foo: void foo( std::function< void( unsigned long ) > func )

Простое решение нежелательно, поскольку оно требует от меня изменения кода, который не принадлежит мне. Есть ли способ, которым я могу как-то преобразовать лямбду только в вызывающий код?


person Jonathan Mee    schedule 26.02.2014    source источник
comment
Почему std::function не рекомендуется? Это самый простой способ принять произвольные типы функций. (В качестве альтернативы вы можете сделать все, что использует функтор, шаблоном, параметризованным типом функтора; это позволит избежать любых накладных расходов, которые могут возникнуть при создании std::function).   -  person Mike Seymour    schedule 26.02.2014
comment
Можете ли вы зафиксировать данные о проблеме по значению?   -  person Adam Burry    schedule 26.02.2014
comment
@AdamBurry: вы не можете преобразовать лямбду в указатель на функцию, если она что-то фиксирует, будь то по значению или ссылке.   -  person Mike Seymour    schedule 26.02.2014
comment
@MikeSeymour, спасибо. Сначала я не понял вопроса. Теперь я вижу, что спрашивают.   -  person Adam Burry    schedule 26.02.2014
comment
@MikeSeymour Под обескураженным я имею в виду, что это не мой код, я могу с ним возиться, но я предпочитаю вносить все изменения в свой код. Так что, что касается искушения или перегрузки функции, которую я пытаюсь вызвать... это обескураживает. Я постараюсь обновить вопрос, чтобы сделать его более ясным.   -  person Jonathan Mee    schedule 26.02.2014
comment
Просто напишите обертку.   -  person cqdjyy01234    schedule 27.02.2014
comment
@user1535111 user1535111 звучит так, будто у вас есть информация, которая мне нужна ... Вы предлагаете мне написать оболочку и передать мою обернутую лямбду в: void foo( void( func* )( unsigned long ) )? Если это так, мне бы очень хотелось, чтобы вы опубликовали ответ, объясняющий, как написать указанную оболочку.   -  person Jonathan Mee    schedule 27.02.2014
comment
@JonathanMee Извините, но когда я начинаю писать код, мне это кажется невозможным. Поскольку обертка должна быть типа func, я возвращаюсь к проблеме: преобразовать лямбду в func.   -  person cqdjyy01234    schedule 27.02.2014
comment
Если ваша программа однопоточная, вы можете использовать глобальный указатель и изменить указатель на текущее состояние. Поскольку указатель является глобальным, вы можете легко написать оболочку. Поскольку func — это обычный указатель на функцию, если указатель имеет какие-либо состояния, он должен иметь статическое хранилище.   -  person cqdjyy01234    schedule 27.02.2014
comment
@user1535111 user1535111 Я понимаю, что вы говорите, за исключением изменения указателя на текущее состояние. Глобальный указатель не будет видеть переменные и параметры экземпляра вызова MyClass к myClassFunc.   -  person Jonathan Mee    schedule 27.02.2014
comment
Реквизит @user1535111, который связал это в его ныне несуществующем ответе. Похоже, что нет хорошего ответа на проблему, и все, что я могу сделать, это просто использовать простое решение, упомянутое в вопросе.   -  person Jonathan Mee    schedule 27.02.2014


Ответы (1)


Да, принять лямбду по ссылке. Поскольку вы не можете назвать его тип, вам понадобится шаблон функции.

person MSalters    schedule 26.02.2014