Как мне сохранить лямбда-выражение для последующего обратного вызова?

#c #lambda #c 11

#c #лямбда #c 11

Вопрос:

Как мне исправить приведенный ниже код для сохранения лямбда-выражения, чтобы я мог вызвать его позже?

Ошибка, которую я получаю в данный момент, заключается в том, что поле ‘m_callback’ имеет неполный тип.

 class Foo
{
    public:
        Foo()  { }
        ~Foo() { }

        template< typename FuncT > 
        void setCallback( FuncTamp;amp; callback )
        {
            m_callback = callback;
        }

    private:
        auto m_callback;   // this line is broken
};
  
 int main(int argc, char** argv)
{
    Foo foo;

    foo.setCallback( [] (int x){ return true; } );

    return 0;
}
  

Комментарии:

1. m_callback = callback; должно быть m_callback = std::forward<FuncT>(callback);

Ответ №1:

auto Ключевое слово can’t be used понравилось. Я рекомендую использовать что-то вроде этого:

 #include <functional>
std::function<bool (int)> m_callback;
  

Это делается из Visual Studio 2010.

Комментарии:

1. хм … … этот ответ хорошо работает, если я заранее знаю сигнатуру лямбда-выражения. Что, если я не знаю сигнатуру (например, я действительно хочу передать void *, который вводится и возвращается позже, но не вызывается внутри Foo)?

2. @kfmfe04: C статически типизирован — вам нужно заранее знать свою подпись. Если вы хотите поддерживать несколько подписей, взгляните на Boost.Variant .

Ответ №2:

auto Ключевое слово может использоваться только в сочетании с выражением инициализации.

Итак … это работает:

 auto callback = [](int x){ return x == 0; };
  

… но это не:

 auto callback;
callback = [](int x){ return x == 0; };
  

Я бы рекомендовал вам использовать что-то вроде function с определенной подписью для представления обратного вызова.

Комментарии:

1. Чтобы быть более точным, во втором случае auto интерпретируется как спецификатор хранилища , например register . В старые времена C , auto был спецификатором хранилища по умолчанию и означал автоматическое хранение (которое для большинства компиляторов является повсеместным стеком). Конечно, поскольку оно используется по умолчанию… уточнять его было не очень полезно, поэтому оно редко использовалось на практике.

2. @MatthieuM.: В C 11, auto поскольку спецификатор хранилища полностью удален.

3. @GMan: о! Я думал, что оно только устарело: x

4. @MatthieuM.: Нет. Для них, конечно, необычно совершать такой прямой переход, но это просто показывает, как вы говорите, насколько это было бесполезно на самом деле.