Добавим в реализацию инициатора, описанного в Листинг 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.
А какой тип аргумента нам указывать при инстанциировании шаблона, ведь тип лямбда-выражения является анонимным? Для этой цели мы будем использовать ключевое слово decltype, которое возвращает тип объявленной переменной (см. Листинг 42).
int capture = 10;
auto lambda = [capture](int eventID) {/*this is a body of lambda*/};
Initiator
Initiator
Initiator
callbackLambda.setup(lambda); //Error: ‘operator’ = attempting to reference a deleted function
callbackLambda.run();
4.4.3. Исполнитель
В Листинг 43 приведены примеры реализации исполнителя для различных типов аргументов. Объявления класса CallbackConverter представлены в Листинг 27 и Листинг 28 п. 4.2.2, инициатор используется из Листинг 41 п. 4.4.2.
class Executor // (1)
{
public:
static void staticCallbackHandler(int eventID, Executor* executor) {}
void callbackHandler(int eventID) {}
void operator() (int eventID) {}
};
void ExternalHandler(int eventID, void* somePointer) {} // (2)
int main()
{
Executor executor; // (3)
int capturedValue = 0;
// (4) Pointer to the external function
using PtrExtFunc = void(*) (int, void*); // (5)
using CallbackExtFunction = CallbackConverter
Initiator
initExtFunction.setup(CallbackExtFunction(ExternalHandler, &executor)); // (8)
// (9) Pointer to the static method
using PtrStaticMethod = void(*) (int, Executor*); // (10)
using CallbacStaticMethod = CallbackConverter
Initiator