Вот две вещи, которые работают. Мы можем создать экземпляр шаблона функции пересылки, чтобы получить указатель на функцию lvalue:
template <class T>
void f(T &&) {}
void(*p)(int &) = f; // Cool!
Мы также можем преобразовать невостребованную общую лямбду с lvalue в указатель функции, принимающий lvalue:
auto l = [](auto &) { };
void (*lp)(int &) = l; // Still cool!
Но, по-видимому, ни один из GCC и Clang не преобразует обобщенную lambda-пересылку в указатель функции, принимающий lvalue:
auto l = [](auto &&) { };
void (*lp)(int &) = l; // Not cool!
Выходы GCC:
<source>:9:21: error: invalid user-defined conversion from '<lambda(auto:1&&)>' to 'void (*)(int&)' [-fpermissive]
void (*lp)(int &) = l;
^
Выходы Clang:
<source>:9:8: fatal error: no viable conversion from '(lambda at <source>:7:10)' to 'void (*)(int &)'
void (*lp)(int &) = l;
^ ~
<source>:7:10: note: candidate template ignored: could not match 'type-parameter-0-0 &&' against 'int &'
auto l = [](auto &&) { };
^
Это все, несмотря на то, что указатель функции-члена, принимающий lvalue, может быть получен из пересылки lambda:
auto lmp = &decltype(l)::operator()<int &>;
template <class...>
struct check;
check<decltype(lmp)> c;
... который выводит тип void (<lambda(auto:1&&)>::*)(int&) const
как ожидалось.
Я считал, что правила обращения коллапса были присущи любому экземпляру шаблона и ожидали, что это сработает. У обоих Clang и GCC есть ошибка, или это фактически не предусмотрено стандартом?