#c #templates #lambda #c 20
Вопрос:
MSVC 2019 позволяет мне определить лямбду, подобную этой, где аргумент шаблона не используется в списке параметров:
auto foo = []<bool B>() {
return B;
};
Однако это приводит к синтаксической ошибке при попытке вызвать его таким образом?
foo<false>();
Как правильно вызывать лямбду с аргументом шаблона, не являющимся параметром?
Комментарии:
1.
foo.operator()<false>();
Ответ №1:
Параметр шаблона используется с operator()
параметром лямбда.
(начиная с C 20) Если в определении лямбда используется явный список параметров шаблона, этот список параметров шаблона используется с оператором().
Вы можете указать аргумент шаблона , не относящийся к типу, для operator()
вызова лямбды в ненормальном стиле, как:
foo.operator()<false>();
Ответ №2:
foo
является объектом функции. У него есть operator()
. Шаблон лямбда-выражения находится на этом операторе, а не на самом имени объекта.
foo<T>
пытается указать имя foo
в качестве аргумента шаблона T
; здесь это недопустимо. foo<T>()
задает аргумент шаблона foo
, затем вызывает ()
результат. Опять же, не то, что здесь происходит.
Переменная шаблона будет работать так, как вы этого хотите:
template<bool B>
auto foo = []() {
return B;
};
такие переменные работают только в глобальной области, но здесь foo<true>()
это сработало бы.
Поскольку лямбда-код на самом деле является классом, генерируемым компилятором:
struct some_secret_name {
template<bool B>
auto operator()() const {
return B;
}
};
some_secret_name foo;
тогда «правильный» способ назвать это уродливым синтаксисом:
foo.operator()<true>();
это, честно говоря, отстой.
Вы можете получить немного лучший синтаксис, как это:
template<class T> struct tag_t {using type=T;};
template<class T> constexpr tag_t<T> tag_v={};
template<auto v> using value_t = std::integral_constant<std::decay_t<decltype(v)>, v>;
template<auto v> constexpr value_t<v> value_v={};
тогда мы сможем сделать
auto foo = []<bool B>(value_t<B>) {
return []{
return B;
};
};
теперь синтаксис таков:
foo(value_v<false>)();
что выглядит немного менее неуклюже, хотя и чересчур волшебно.
foo
теперь это лямбда, которая создает лямбды, внешняя лямбда принимает параметры вашего шаблона в качестве аргументов функции, а внутренняя лямбда-это тело.