Форум » C/C++ » Шаблонные или, по-другому, обобщенные лямбда-выражения. » Ответить

Шаблонные или, по-другому, обобщенные лямбда-выражения.

Сыроежка: Как известно в качестве спецификаторов типов для параметров лямбда-выражений можно использовать ключевое слово auto, и тогда тип параметров будет выведен компилятором в момент вызова лямбда выражения с конкретными аргументами. Например, [pre2] #include <iostream> #include <string> int main() { auto plus( []( auto l, auto r ) { return l + r; } ); std::cout << plus( 1, 2 ) << '\n'; std::cout << plus( 1.5, 2 ) << '\n'; std::cout << plus( std::string( "Hello, " ), "World!" ) << '\n'; } [/pre2] Вывод программы на консоль: [pre2] 3 3.5 Hello, World! [/pre2] В первом вызове лямбда-выражения оба аргумента имеют тип int и тип возвращаемого значения также имеет тип int. Во втором вызове лямбда-выражения первый аргумент имеет тип double, и второй аргумент - тип int. Тип возвращаемого значения в этом случае есть тип double. В третьем вызове лямбда выражения первый аргумент имеет тип std::string, а второй аргумент - тип const char *. Тип возвращаемого значения есть тип std::string. То есть используя спецификаторы auto для описания параметров, мы создали шаблонное или обобщенное лямбда-выражение. Но иногда требуется, чтобы, например, оба параметра (или несколько параметров) имели один и тот же тип. В этом случае уже нельзя использовать спецификатор auto, так как это позволит указывать аргументы разных типов. Для подобных случаев в стандарте C++ 2017 введена возможность явно указать список шаблонных параметров. Например, вышеприведенное лямбда-выражение может быть переписано следующим образом [pre2] auto plus( []<typename T>( T l, T r ) { return l + r; } ); [/pre2] В этом случае оба аргумента при вызове лямбда-выражения должны иметь один и тот же тип. Рассмотрите [pre2] #include <iostream> #include <string> int main() { auto plus( []<typename T>( T l, T r ) { return l + r; } ); std::cout << plus( 1, 2 ) << '\n'; // std::cout << plus( 1.5, 2 ) << '\n'; std::cout << plus( std::string( "Hello, " ), std::string( "World!" ) ) << '\n'; // std::cout << plus( std::string( "Hello, " ), "World!" ) << '\n'; } [/pre2] Вывод программы на консоль: [pre2] 3 Hello, World! [/pre2] Закомментированные вызовы лямбда-выражения уже не будут компилироваться. А что если нужно создать шаблонное лямбда выражение, но которое не имеет шаблонных параметров? Например, [pre2] auto create_vector = []<typename T>( size_t n = 0 ) { std::vector<T> v; v.reserve( n ); return v; };[/pre2] Как в этом случае вызвать лямбда-выражение и сообщить ему требуемый шаблонный аргумент? Это можно сделать посредством явного вызова оператора-функции. Ниже показано, как это будет выглядеть [pre2] #include <iostream> #include <vector> int main() { auto create_vector = []<typename T>( size_t n = 0 ) { std::vector<T> v; v.reserve( n ); return v; }; auto v = create_vector.operator()<int>( 10 ); std::cout << "capacity = " << v.capacity() << std::endl; } [/pre2] Вывод программы на консоль: [pre2] capacity = 10 [/pre2]

Ответов - 1

Сыроежка: В продолжение темы будет познавательно привести следующий вопрос Is it possible to define a lambda in C++ with default generic argument?, заданный на днях на сайте Stackoverflow. Автор вопроса (кстати сказать, старший инженер-программист - Senior Software Engineer at Aimsun) спрашивает: можно ли указать шаблонный аргумент по умолчанию для шаблонного параметра лямбда-выражения. В качестве примера он приводит такой функциональный объект [pre2] struct Lambda{ template<typename T=int> auto operator()(T i=1){ return i;} };[/pre2] который хочет определить в виде лямбда выражения. Сделать это достаточно просто, зная, что теперь в лямбда выражении можно явно указывать шаблонные параметры. Вот как будет выглядеть такое лямбда-выражение, показанное в следующей демонстрационной программе [pre2] #include <iostream> int main() { auto l = []<typename T = int>( T i = T( 1 ) ) { return i; }; std::cout << l() << std::endl; } [/pre2] Вывод программы на консоль, очевидно, будет [pre2] 1 [/pre2] Замечу, что когда я писал это сообщение, еще ни одного комментария или ответа к вопросу на Stackoverflow не появилось.



полная версия страницы