Home > Mobile >  Calling lambda with non-parameter template argument
Calling lambda with non-parameter template argument

Time:09-25

MSVC 2019 allow me to define a lambda like this, where the template argument is not used in the parameter list:

auto foo = []<bool B>() {
  return B;
};

However, it gives syntax error when trying to call it like this?

foo<false>();

What is the correct way to call a lambda with a non-parameter template argument?

CodePudding user response:

The template parameter is used with operator() of lambda.

(since C 20) If the lambda definition uses an explicit template parameter list, that template parameter list is used with operator().

You can specify the non-type template argument for operator(), call the lambda in an unnormal style as:

foo.operator()<false>();

CodePudding user response:

foo is a function object. It has an operator(). The template on a lambda is on that operator, not on the object name itself.

foo<T> attempts to give the name foo a template argument T; that isn't valid here. foo<T>() gives the template argument to foo, then calls () on the result. Again, not what is going on here.

A template variable would work the way you want this to:

template<bool B>
auto foo = []() {
  return B;
};

such variables only work in global scope, but here foo<true>() would work.

As a lambda is actually a compiler-generate class:

struct some_secret_name {
  template<bool B>
  auto operator()() const {
    return B;
  }
};
some_secret_name foo;

then the "right" way to call it is the ugly syntax:

foo.operator()<true>();

this, honestly, sucks.

You can get slightly better syntax like this:

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={};

then we can do

auto foo = []<bool B>(value_t<B>) {
  return []{
    return B;
  };
};

now the syntax is:

foo(value_v<false>)();

which looks a bit less cludgy, if overly magical.

foo is now a lambda that makes lambdas, the outer lambda takes your template parameters as function arguments, and the inner lambda is the body.

  • Related