Обратные вызовы в C++ | страница 49



– пакет параметров, определяющих типы передаваемых в функцию аргументов. При объявлении перегруженных операторов (строки 3, 8, 10), вместо конкретного типа возвращаемого значения подставляется параметр шаблона Return, вместо конкретных типов входных параметров подставляется ArgumentList. В местах, где происходит вызов оператора, пакет параметров раскрывается (строки 9 и 11), что означает, что вместо arguments будет подставлен список переменных с типами, заданными в пакете параметров.


Теперь в универсальном аргументе можно настраивать сигнатуру, как это продемонстрировано в Листинг 49.

Листинг 49. Использование аргумента с настройкой сигнатуры

>void ExternalHandler1(int eventID) {/*Do something*/}            // (1)

>int  ExternalHandler2(int eventID, int contextID) { return 0; }  // (2)


>struct CallbackHandler  // (3)

>{

>  void operator() (int eventID) {}

>  bool operator() (int eventID, int contextID) { return false; }

>};


>int main()

>{

>  int capturedValue = 100;

>  CallbackHandler callbackObject;           // (4)


>  UniArgument argument1;         // (5)

>  UniArgument argument2;    // (6)


>  argument1 = ExternalHandler1;  // (7)

>  argument2 = ExternalHandler2;  // (8)


>  argument1 = callbackObject;    // (9)

>  argument2 = callbackObject;    // (10)


>  argument1 = [capturedValue](int eventID) {/*Do something*/};                           // (11)

>  argument2 = [capturedValue](int eventID, int contextID) { /*DoSomething*/return 0; };  // (12)


>  argument1(3);               // (13)

>  int res = argument2(4, 5);  // (14)


>  return res;

>}


В строках 1 и 2 объявлены две внешние функции с различными сигнатурами. В строке 3 объявлен функциональный объект, в котором перегружены операторы вызова функции с такими же сигнатурами. В строке 4 объявлен экземпляр указанного объекта.

В строках 5 и 6 объявлены универсальные аргументы, в которых с помощью параметров шаблона настраивается нужная сигнатура. Далее этим аргументам будут присваиваться различные объекты вызова в зависимости от заданной сигнатуры.

В строках 7 и 8 в аргумент передаются внешние функции. В строках 9 и 10 передается функциональный объект, у которого, в зависимости от настроенной сигнатуры будет вызван соответствующий перегруженный оператор. В строках 11 и 12 передаются лямбда-выражения. В строках 13 и 14 осуществляются вызовы в соответствии с заданной сигнатурой.

4.5.3. Вызов метода класса

В текущей реализации универсальный аргумент может работать с любыми объектами вызова, за исключением методов класса. Это связано с тем, что вызов метода класса имеет другой синтаксис, отличный от вызова функции. Как добавить поддержку вызова методов? Можно предложить следующее решение: при настройке объекта назначать указатель на метод, аналогично обычной функции, а при вызове передавать экземпляр класса как дополнительный аргумент.