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.