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 是否正确,在第二种情况下哪些规则使非 constexpr 变量的使用v
无效,在第三种情况下x
有效。
编辑2:第一个问题现在很清楚: https ://gcc.gnu.org/bugzilla/show_bug.cgi?id=84421
clang 是对的,GCC 7 也接受了代码。该错误将在 GCC 8 的最终版本中修复。