On-line: гостей 1. Всего: 1 [подробнее..]
Программисты всех стран, объединяйтесь!

АвторСообщение



ссылка на сообщение  Отправлено: 01.06.18 16:54. Заголовок: Шаблонные или, по-другому, обобщенные лямбда-выражения.


Как известно в качестве спецификаторов типов для параметров лямбда-выражений можно использовать ключевое слово auto, и тогда тип параметров будет выведен компилятором в момент вызова лямбда выражения с конкретными аргументами.

Например,

 
#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';
}


Вывод программы на консоль:

 
3
3.5
Hello, World!


В первом вызове лямбда-выражения оба аргумента имеют тип int и тип возвращаемого значения также имеет тип int.
Во втором вызове лямбда-выражения первый аргумент имеет тип double, и второй аргумент - тип int. Тип возвращаемого значения в этом случае есть тип double.
В третьем вызове лямбда выражения первый аргумент имеет тип std::string, а второй аргумент - тип const char *. Тип возвращаемого значения есть тип std::string.

То есть используя спецификаторы auto для описания параметров, мы создали шаблонное или обобщенное лямбда-выражение.

Но иногда требуется, чтобы, например, оба параметра (или несколько параметров) имели один и тот же тип. В этом случае уже нельзя использовать спецификатор auto, так как это позволит указывать аргументы разных типов.

Для подобных случаев в стандарте C++ 2017 введена возможность явно указать список шаблонных параметров. Например, вышеприведенное лямбда-выражение может быть переписано следующим образом

 
auto plus( []<typename T>( T l, T r ) { return l + r; } );


В этом случае оба аргумента при вызове лямбда-выражения должны иметь один и тот же тип.

Рассмотрите

 
#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';
}


Вывод программы на консоль:

 
3
Hello, World!


Закомментированные вызовы лямбда-выражения уже не будут компилироваться.

А что если нужно создать шаблонное лямбда выражение, но которое не имеет шаблонных параметров?

Например,

 
auto create_vector = []<typename T>( size_t n = 0 )
{
std::vector<T> v;
v.reserve( n );
return v;
};


Как в этом случае вызвать лямбда-выражение и сообщить ему требуемый шаблонный аргумент?

Это можно сделать посредством явного вызова оператора-функции. Ниже показано, как это будет выглядеть

 
#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;
}


Вывод программы на консоль:

 
capacity = 10


Спасибо: 0 
ПрофильЦитата Ответить
Ответов - 1 [только новые]





ссылка на сообщение  Отправлено: 08.06.18 17:16. Заголовок: В продолжение темы б..


В продолжение темы будет познавательно привести следующий вопрос Is it possible to define a lambda in C++ with default generic argument?, заданный на днях на сайте Stackoverflow.

Автор вопроса (кстати сказать, старший инженер-программист - Senior Software Engineer at Aimsun) спрашивает: можно ли указать шаблонный аргумент по умолчанию для шаблонного параметра лямбда-выражения. В качестве примера он приводит такой функциональный объект

 
struct Lambda{
template<typename T=int>
auto operator()(T i=1){ return i;}
};


который хочет определить в виде лямбда выражения.

Сделать это достаточно просто, зная, что теперь в лямбда выражении можно явно указывать шаблонные параметры.

Вот как будет выглядеть такое лямбда-выражение, показанное в следующей демонстрационной программе

 
#include <iostream>

int main()
{
auto l = []<typename T = int>( T i = T( 1 ) ) { return i; };

std::cout << l() << std::endl;
}


Вывод программы на консоль, очевидно, будет
 
1


Замечу, что когда я писал это сообщение, еще ни одного комментария или ответа к вопросу на Stackoverflow не появилось.

Спасибо: 0 
ПрофильЦитата Ответить
Ответ:
1 2 3 4 5 6 7 8 9
большой шрифт малый шрифт надстрочный подстрочный заголовок большой заголовок видео с youtube.com картинка из интернета картинка с компьютера ссылка файл с компьютера русская клавиатура транслитератор  цитата  кавычки моноширинный шрифт моноширинный шрифт горизонтальная линия отступ точка LI бегущая строка оффтопик свернутый текст

показывать это сообщение только модераторам
не делать ссылки активными
Имя, пароль:      зарегистрироваться    
Тему читают:
- участник сейчас на форуме
- участник вне форума
Все даты в формате GMT  3 час. Хитов сегодня: 5
Права: смайлы да, картинки да, шрифты да, голосования нет
аватары да, автозамена ссылок вкл, премодерация откл, правка нет