Второе определение - это шаблон переменной. Он не определяет лямбду operator()
как шаблон, а принимает пакет параметров для типов аргументов operator()
. Результирующий operator()
является обычной функцией-членом типа замыкания инстанцированной переменной. Здесь невозможно вывести аргументы шаблона.
Таким образом, когда вы пишете lamd<int>
, переменная получает тип замыкания с operator()(int)
, а не что-то вызываемое с 3 целыми числами.
Как уже упоминалось, вместо этого вы можете использовать общую лямбду.
В C ++ 20, если вам нужно, чтобы лямбда-типы аргументов были названы и выведены, вы можете использовать синтаксис:
auto lamd = []<typename... Pack>(Pack...) {}
определит оператора как шаблон, принимая пакет параметров, и оставит дверь открытой для вывода аргумента шаблона.