Как работает общая лямбда в C++14?


Как работает общая лямбда (auto ключевое слово как тип аргумента) в стандарте C++14?

Он основан на шаблонах C++, где для каждого другого типа аргумента компилятор генерирует новую функцию с тем же телом, но замененными типами (полиморфизм времени компиляции) или он более похож на дженерики Java (стирание типа)?

пример кода:

auto glambda = [](auto a) { return a; };
3 99

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;