In the code below, on the first form, gcc complains about having a lambda in a template parameter. In the second form, gcc complains about lambda_function_pointer not having external linkage. Clang compiles and runs the code just fine even with -pedantic.
The +
in front of the lambda is to coerce it to decay into a function pointer.
template<auto f>
void func() {
f();
}
void g();
int main() {
func<+[](){}>(); // gcc complains about lambda in template args
constexpr auto lambda_function_pointer = +[](){};
func<lambda_function_pointer>(); // gcc complains about not having external linkage
}
live: https://godbolt.org/g/ey5uo7
Thank you.
edit: https://timsong-cpp.github.io/cppwp/n4659/expr.prim.lambda#2
mentions lambdas not appearing in template parameters for the sake of the lambda not being in the signature, but with the +
, it gets rid of the lambda type.
edit2: This may be relevant for the linkage portion of the question: Why did C++03 require template parameters to have external linkage?
For example, given a specialization Stack<int>, “int” is a template argument. Instantiation: This is when the compiler generates a regular class, method, or function by substituting each of the template's parameters with a concrete type.
A template parameter is a special kind of parameter that can be used to pass a type as argument: just like regular function parameters can be used to pass values to a function, template parameters allow to pass also types to a function.
A template argument for a template template parameter is the name of a class template. When the compiler tries to find a template to match the template template argument, it only considers primary class templates. (A primary template is the template that is being specialized.)
A template non-type parameter is a template parameter where the type of the parameter is predefined and is substituted for a constexpr value passed in as an argument. A non-type parameter can be any of the following types: An integral type. An enumeration type. A pointer or reference to a class object.
func<+[](){}>
is ill-formed in C++17 per the exact paragraph you linked to. The non-normative note simply explains the motivation for the normative prohibition. It does not - and cannot - limit it. This restriction has been removed in the current working draft by P0315, so it has a good chance of making C++20.
Pre-C++17, a lambda-expression cannot be evaluated inside constant expressions.
The "linkage" part is a duplicate of Can I use the result of a C++17 captureless lambda constexpr conversion operator as a function pointer template non-type argument?. It's a GCC bug.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With