Is a lambda expression a legal default (non-type template) argument and, if so, wouldn’t this imply that each instantiation using such a default argument instantiates a unique specialization?
Yes, it means that given your templated variable:
template<auto l = [](){}>
constexpr auto default_lambda = l;
every call to default_lambda
will produce a new template instantiation by generating a new unique closure type and thus provides a new way to capture a metaprogramming state.
Thus, every expressions that use default_lambda
have to be reevaluated. If the state of the compiler changed since the last instantiation and if we used it in a dependent expression (ex: check that a type is defined) then the result of the expression might change.
For example:
struct X; // not defined
template <typename T, auto = default_lambda<>>
consteval bool is_defined() {
if constexpr (requires { T{}; }) {
return true;
} else {
return false;
}
}
static_assert(is_defined<X>() == false);
struct X {};
static_assert(is_defined<X>() == true);