https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92320

            Bug ID: 92320
           Summary: Constexpr function pointer derived from lambda is not
                    accepted as template parameter
           Product: gcc
           Version: 9.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jleahy+gcc at gmail dot com
  Target Milestone: ---

The following code is not accepted by the compiler, whereas I believe it is
well-formed according to the standard:

template<auto V>
void templ() {}

void foo() {
    constexpr auto * a = +[](){};
    templ<a>();
}

Here is a less condensed version that demonstrates a number of similar
circumstances: (only the very last case is rejected by GCC)

template<auto V>
void templ() {}

void dummy(){}

void foo() {
    constexpr int a = 7 + 3;
    templ<a>();

    templ<dummy>();

    typedef void(FPtr)();
    constexpr FPtr * b = &dummy;
    templ<b>();

    constexpr FPtr * c = [](){};
    templ<c>();
}

Generally speaking it seems that GCC is perfectly happy instantiating a
template with a constexpr (as you would hope) and with a constexpr function
pointer even, but only if that function pointer derives from a free function.

If a constexpr function pointer derives from the constexpr conversion of a
lambda to a function pointer than GCC rejects the code with an error like the
below:

error: 'foo()::<lambda()>::_FUN' is not a valid template argument for type
'void (*)()' because 'static constexpr void foo()::<lambda()>::_FUN()' has no
linkage

This code is accepted by clang.

Reply via email to