Взаимодействие "if constexpr" с предупреждением "try in constexpr function"
Я утверждаю, что эта программа должна быть правильно сформирована: она объявляет функцию-член 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
в функцию - член non-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;
}
}
};
Это
- ошибка как в GCC, так и в Clang?
- дефект в стандарте, который GCC и Clang добросовестно внедряют?
- проблема качества реализации из-за "условного соответствия"
foo()
?
(Неактуальный фон: я внедряю constexpr any::emplace<T>()
для версии с поддержкой распределителя any
чей распределитель может быть constexpr-per- P0639 (то есть может отсутствовать deallocate
функция-член) или не может. В первом случае мы не хотим или не нуждаемся в try
; в последнем случае нам нужно try
для того, чтобы позвонить deallocate
если конструктор T
броски.)
1 ответ
Компиляторы подчиняются Стандарту. В проекте C++17 N4659 говорится ([dcl.constexpr]/(3.4.4)):
Определение функции constexpr должно удовлетворять следующим требованиям:
...
его функция-тело должно быть
= delete
,= default
или составной оператор, который не содержит
...
пробный блок, или
...
И ни одно из правил для "исключенных заявлений", таких как else
утверждение в вашем S<int>::foo
переопределить это правило. Единственные особые вещи, которые указаны в отношении отброшенных операторов, - это то, что отброшенные операторы не создаются, а использование odr в опущенных операторах не требует определения используемого объявления и отбрасывается return
операторы игнорируются при определении истинного типа возврата функции с типом возврата заполнителя.
Я не видел ни одной существующей проблемы C++, обсуждающей это, и документ P0292R1, в котором предлагалось if constexpr
не касается взаимодействия с функциями constexpr.