Почему в контексте constexpr нельзя использовать лямбду, когда она используется для указания функции?
Рассмотрим пример:
template <void (*Foo)()>
struct S {
};
int main() {
struct A {
static void x() { }
};
S<&A::x> s;
}
Код компилируется в clang, gcc утверждает, что x
не имеет привязки...
Для аналогичного примера просто при использовании лямбда-выражения:
template <void (*Foo)()>
struct S {
};
int main() {
auto lambda = []{};
S<+lambda> s;
}
Оба gcc и clang соглашаются не компилировать код: согласно gcc функция, возвращаемая unary +, не имеет привязки, состояния clang в отличие от того, что оператор-оператор в функцию не объявлен как constexpr. Есть ли какие-либо причины, чтобы запретить использование lambda cast для функции в контексте constexpr?
Найдите ниже ошибки, созданные компиляторами и живые демонстрации:
gcc:
prog.cc:7:14: error: 'main():: _ FUN' не является допустимым аргументом шаблона для типа 'void (*)()', потому что 'static constexpr void main():: _FUN() 'не имеет привязки
clang:
prog.cc:7:8: note: функция non-constexpr 'operator void (*)()' не может использоваться в постоянном выражении
Ответы
Ответ 1
Clang еще не реализовал constexpr
lambdas.
GCC отстает по-другому. [temp.arg.nontype]/2 только интересное ограничение состоит в том, что аргумент должен быть постоянным выражением. Но [expr.const]/(5.2) делает его одним, поэтому совершенно корректным. Возможно, GCC еще не реализовал N4198, что устранило требование связывания.
Обратите внимание, что оба аргумента шаблона указателя функции constexpr
lambdas и no-linkage - это функции post С++ 14.