Подтвердить что ты не робот

Почему в контексте 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 (*)()' не может использоваться в постоянном выражении

4b9b3361

Ответ 1

Clang еще не реализовал constexpr lambdas.

GCC отстает по-другому. [temp.arg.nontype]/2 только интересное ограничение состоит в том, что аргумент должен быть постоянным выражением. Но [expr.const]/(5.2) делает его одним, поэтому совершенно корректным. Возможно, GCC еще не реализовал N4198, что устранило требование связывания.

Обратите внимание, что оба аргумента шаблона указателя функции constexpr lambdas и no-linkage - это функции post С++ 14.