struct A{
constexpr operator bool()const{ return true; }
};
int main(){
auto f = [](auto v){ if constexpr(v){} };
A a;
f(a);
}
clang 6 принимает Код, GCC 8 отклоняет его:
$ g++ -std=c++17 main.cpp
main.cpp: In lambda function:
main.cpp:6:37: error: 'v' is not a constant expression
auto f = [](auto v){ if constexpr(v){} };
^
Кто прав и почему?
Когда я беру параметр для ссылки, оба отклоняют код:
struct A{
constexpr operator bool()const{ return true; }
};
int main(){
auto f = [](auto& v){ if constexpr(v){} };
constexpr A a;
f(a);
}
Скомпилировано с помощью clang 6:
$ clang++ -std=c++17 main.cpp
main.cpp:6:40: error: constexpr if condition is not a constant expression
auto f = [](auto& v){ if constexpr(v){} };
^
main.cpp:8:6: note: in instantiation of function template specialization
'main()::(anonymous class)::operator()<const A>' requested here
f(a);
^
1 error generated.
Когда я копирую параметр в локальную переменную, оба принимают код:
struct A{
constexpr operator bool()const{ return true; }
};
int main(){
auto f = [](auto v){ auto x = v; if constexpr(x){} };
A a;
f(a);
}
Изменить: я уверен, что второй и третий случаи будут правильно обработаны обоими компиляторами. Однако я не знаю, что это за правило.
В первом случае я подозреваю, что clang прав, потому что он похож на второй. Я хотел бы знать, правильны ли в первом случае clang или GCC и какие правила во втором случае делают использование переменной not-constexpr v
недействительной, а в третьем случае x
действительным.
Изменить 2: теперь первый вопрос ясен: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84421
clang был прав, GCC 7 тоже принял код. Ошибка будет исправлена в финальной версии GCC 8.
v
постоянным выражением или почему непостоянное выражение нельзя использовать там, где оно требуется? Какие исследования вы провели по этой теме? - person user167921   schedule 16.02.2018std::bool_constant
, который, хотя и неconstexpr
, имеет оператор преобразованияconstexpr
вbool
. - person Quentin   schedule 16.02.2018constexpr
) - person Ben Voigt   schedule 16.02.2018