Обратные вызовы в C++ | страница 41
>int capture = 10;
>auto lambda = [capture](int eventID) {/*this is a body of lambda*/};
>lambda(10); //lambda call
Однако указанный способ не будет работать, когда требуется сохранить лямбда-выражение в классе. Мы не можем объявить переменную – член класса с типом auto, потому что это означало бы объявление переменной заранее не определенного типа, что не допускается.
Организовать хранение лямбда-выражения внутри класса можно с помощью шаблона, в котором тип выражения будет параметризован. Однако при инстанциировании шаблона переменной, предназначенной для хранения, значение должно быть присвоено в конструкторе. Это нельзя сделать позже, потому что в объекте-замыкании, генерируемым компилятором, запрещен оператор присваивания. Это и понятно: поскольку тип каждого объявленного лямбда-выражения является уникальным, то мы не можем ему ничего присваивать, кроме самого себя.
Добавим в реализацию инициатора, описанного в Листинг 37 п. 4.4.1, два конструктора. Один конструктор будет с переменной – аргументом обратного вызова для инициализации члена класса. Другой конструктор будет без аргументов (конструктор по умолчанию), чтобы оставить возможность отложенной настройки (Листинг 41).
>template
>class Initiator
>{
>public:
> Initiator() {}
> Initiator(const CallbackArgument& argument) : callbackHandler(argument) {}
> void setup(const CallbackArgument& argument)
> {
> callbackHandler = argument;
> }
> void run()
> {
> int eventID = 0;
> //Some actions
> callbackHandler(eventID);
> }
>private:
> CallbackArgument callbackHandler;
>};
Для любых типов аргументов обратного вызова, кроме лямбда-выражений, допускается использование обоих конструкторов. Для лямбда-выражений допускается использование только конструктора с аргументом, при попытке использования конструктора по умолчанию компилятор выдаст ошибку. Кроме того, в этом случае нельзя будет вызвать метод setup – также будет сгенерирована ошибка. Таким образом, использование инициатора с лямбда-выражением не предполагает динамической модификации: настройка происходит один раз в конструкторе при инстанциировании шаблона, и больше изменить ее нельзя20.
А какой тип аргумента нам указывать при инстанциировании шаблона, ведь тип лямбда-выражения является анонимным? Для этой цели мы будем использовать ключевое слово