8

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?

xaxxon
  • 19,189
  • 5
  • 50
  • 80
  • Since you use a C++11 tag, do you expect an answer based on C++11? – xskxzr Feb 19 '18 at 07:05
  • I changed the question title to more accurately reflect the core issue, which is about external linkage. GCC will happily accept the second case, if you move `lambda_function_pointer` to file scope (which gives it external linkage.) – Nikos C. Feb 23 '18 at 08:22
  • @NikosC I do not believe that title change is correct. There's more at play here, such as whether the lambda is allowed to appear directly or only through a helper variable, and precisely what is and isn't specified for the implicit conversion to function pointer type. –  Feb 23 '18 at 08:25
  • @hvd Indeed. I have trouble coming up with a good question title, in order for this to get more attention (it is a very interesting case, imo.) – Nikos C. Feb 23 '18 at 08:28

1 Answers1

3

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.

T.C.
  • 133,968
  • 17
  • 288
  • 421