Как работает generic lambda в C++14?
Как работает общая лямбда (auto
ключевое слово как тип аргумента) в стандарте C++14?
основан ли он на шаблонах C++, где для каждого другого типа аргумента компилятор генерирует новую функцию с тем же телом, но замененными типами (полиморфизм времени компиляции) или он больше похож на дженерики Java (стирание типа)?
пример кода:
auto glambda = [](auto a) { return a; };
3 ответов
общие лямбды были введены в C++14
.
просто тип закрытия, определенный лямбда-выражением, будет иметь templated оператор вызова, а не обычный, не шаблонный оператор вызова C++11
лямбда (конечно, когда auto
появляется хотя бы один раз в списке параметров).
так что твой пример:
auto glambda = [] (auto a) { return a; };
сделает glambda
экземпляр этого тип:
class /* unnamed */
{
public:
template<typename T>
T operator () (T a) const { return a; }
};
в пункте 5.1.2 / 5 проекта стандарта C++14 n3690 указывается, как определяется оператор вызова типа замыкания данного лямбда-выражения:
тип закрытия для неродового лямбда-выражения имеет открытый оператор вызова встроенной функции (13.5.4) чьи параметры и тип возвращаемого значения описываются предложением parameter-declaration - и trailing-return-type соответственно. для общей лямбды, тип закрытия имеет открытый вызов встроенной функции шаблон члена оператора (14.5.2), список параметров-шаблонов которого состоит из одного изобретенного типа template-parameter для каждого появления auto в предложении parameter-declaration-Lambda в порядке появления. Изобретенный тип template-parameter является пакетом параметров, если соответствующий параметр-declaration объявляет пакет параметров функции (8.3.5). Возвращаемые параметры типа и функции вызова функции шаблон оператора являются производными от типа и параметра-declarationclause трейлинг-возврата лямбда-выражения заменяя каждое вхождение auto в спецификаторах decl предложения parameter-declaration на название соответствующего придуманного шаблона-параметра.
и наконец:
похоже ли это на шаблоны, где для каждого другого типа аргумента компилятор генерирует функции с тем же телом, но измененными типами или он больше похож на Java генерики?
как объясняется в предыдущем абзаце, общие лямбды - это просто синтаксический сахар для уникальных неназванных функторов с шаблонным оператором вызова. Это должно ответить на ваш вопрос :)
к сожалению, они не являются частью C++11 (http://ideone.com/NsqYuq):
auto glambda = [](auto a) { return a; };
int main() {}
С g++ 4.7:
prog.cpp:1:24: error: parameter declared ‘auto’
...
, как это может быть реализовано в C++14 в соответствии с предложение Portland для общих лямбд:
[](const& x, & y){ return x + y; }
это дало бы по большей части обычное создание анонимного класса функтора, но с отсутствием типов компилятор испустил бы шаблонный член -operator()
:
struct anonymous
{
template <typename T, typename U>
auto operator()(T const& x, U& y) const -> decltype(x+y)
{ return x + y; }
};
или согласно более новому предложению предложение для общих (полиморфных) лямбда-выражений
auto L = [](const auto& x, auto& y){ return x + y; };
--->
struct /* anonymous */
{
template <typename T, typename U>
auto operator()(const T& x, U& y) const // N3386 Return type deduction
{ return x + y; }
} L;
так что да, для каждой перестановки параметров возникнет новый экземпляр, однако члены этого функтора все равно будут разделены (т. е. захваченные аргументы).
это предлагаемая функция C++14 (не в C++11), аналогичная (или даже эквивалентная) шаблонам. Например, N3559 обеспечивает такой пример:
например, это общее лямбда-выражение, содержащее оператор:
auto L = [](const auto& x, auto& y){ return x + y; };
может привести к созданию типа закрытия и объекта, который ведет себя аналогично приведенной ниже структуре:
struct /* anonymous */ { template <typename T, typename U> auto operator()(const T& x, U& y) const // N3386 Return type deduction { return x + y; } } L;