Я утверждаю что эта программа должен быть правильно сформирован: он объявляет функцию-член constexpr S<int>
, Однако и GCC, и Clang отклоняют эту программу.
template<class T>
struct S {
constexpr int foo() {
if constexpr (std::is_same_v<T, int>) {
return 0;
} else {
try {} catch (...) {}
return 1;
}
}
};
int main()
{
S<int> s;
return s.foo(); // expect "return 0"}
GCC говорит:
ошибка: попробуйте в функции constexpr
Clang говорит:
ошибка: оператор не разрешен в функции constexpr
Ни один из них, кажется, не замечает, что оператор «try» находится в отброшенной ветви if constexpr
заявление.
Если я фактор try
/catch
в без constexpr функция-член void trycatch()
затем и Clang, и GCC снова довольны кодом, хотя его поведение должно быть эквивалентно несчастной версии.
template<class T>
struct S {
void trycatch() {
try {} catch (...) {}
}
constexpr int foo() {
if constexpr (std::is_same_v<T, int>) {
return 0;
} else {
trycatch(); // This is fine.
return 1;
}
}
};
Это
foo()
?(Неактуальный фон: я внедряю constexpr any::emplace<T>()
для версии с поддержкой распределителя any
чей распределитель может быть constexpr-per-P0639 (то есть может не хватать deallocate
функция-член) или не может. В первом случае мы не хотим или не нуждаемся в try
; в последнем случае нам нужно try
для того, чтобы позвонить deallocate
если конструктор T
броски.)
Компиляторы подчиняются Стандарту. В проекте C ++ 17 N4659 говорится ([dcl.constexpr] / (3.4.4)):
Определение функции constexpr должно удовлетворять следующим требованиям:
…
его функция тела должен быть
= delete
,= default
или компаунд-заявление что не содержит
…
попробуйте-блок, или же
…
И ни одно из правил для «исключенных заявлений», таких как else
утверждение в вашем S<int>::foo
переопределить это правило. Единственные особые вещи, которые указаны в отношении отброшенных операторов, — это то, что отброшенные операторы не создаются, а использование odr в опущенных операторах не требует определения используемого объявления и отбрасывается return
операторы игнорируются при определении истинного типа возврата функции с типом возврата заполнителя.
Я не видел ни одной существующей проблемы C ++, обсуждающей это, и документ P0292R1, в котором предлагалось if constexpr
не касается взаимодействия с функциями constexpr.
Других решений пока нет …