Как работает общая лямбда в C++14?
Как работает общая лямбда (auto
ключевое слово как тип аргумента) в стандарте C++14?
Он основан на шаблонах C++, где для каждого другого типа аргумента компилятор генерирует новую функцию с тем же телом, но замененными типами (полиморфизм времени компиляции) или он более похож на дженерики Java (стирание типа)?
пример кода:
auto glambda = [](auto a) { return a; };
3 ответа:
общие лямбды были введены в
C++14
.просто, тип замыкания, определенный лямбда-выражением, будет иметь шаблона оператор вызова, а не обычный, не шаблонный оператор вызова
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-clause лямбда-выражения и trailing-return-type соответственно. для общей лямбды, тип закрытия имеет открытый встроенный вызов функции шаблон члена оператора (14.5.2), чей шаблон-параметр-список состоит из одного изобретенного типа шаблона-параметра для каждого вхождения auto в предложении parameter-declaration-Lambda, в порядке появления. Придуманный шаблон-параметр типа является пакет параметр если соответствующий параметр-декларации провозглашает пакет параметров функции (8.3.5). Возвращаемый тип и параметры функции вызова функции шаблон оператора являются производными от лямбда-выражения trailing-return-type и parameter-declarationclause заменяя каждое вхождение auto в Децл-спецификаторах предложения 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 в соответствии с предложение Портленда для общих лямбд:
[](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;