Лямбда-функции с параметрами шаблона, а не с параметрами функции - PullRequest
8 голосов
/ 23 сентября 2019

Почему первый вызов не компилируется?

auto get1 = []<int B>() { return B; };
auto get2 = []<typename B>(B b) { return b; };

int main()
{
    get1<5>(); // error: no match for operator<
    get2(5);   // ok
}

Причина, по которой я это использую, состоит в том, что в коде многократно повторяется выражение.

Конечно, я могу использовать реальный шаблон функции, но просто мне любопытно ПОЧЕМУ.

1 Ответ

10 голосов
/ 23 сентября 2019

Это легче понять, если учесть, как выглядит эквивалентный тип класса для вашего get1:

struct get1_t {
    template <int B> operator()() const { return B; }
};

get1_t get1;

get1<5>(); // error

Вы пытаетесь предоставить явный параметр шаблона для оператора вызова, но синтаксическивы делаете то, что выглядит как предоставление параметров шаблона для самого get1 (т.е. как если бы get1 был переменным шаблоном).Чтобы предоставить параметр шаблона для оператора вызова, вы должны сделать это напрямую:

get1.operator()<5>(); // ok

Или реструктурировать оператор вызова, чтобы получить что-то выводимое:

template <int B> struct constant { };
get1(constant<5>{});

Или реструктурируйте все это так, чтобы оно превратилось в шаблон переменной, который выглядит так:

template <int B>
auto get1 = [] { return B; };

Теперь get1<5> сам по себе является лямбда-выражением, которое вы вызываете.То есть вместо лямбды с шаблоном оператора вызова у нас есть переменная лямбда-шаблон, которая сама по себе не является шаблоном.

...