[英]constexpr bug in clang but not in gcc?
Let's take this simple example: 我们来看一个这个简单的例子:
#include <iostream>
namespace foo {
constexpr int main(int argc, char* argv[]) {
// code
}
}
int main(int argc, char* argv[])
{
return foo::main(argc, argv);
}
Depend on what code is, clang will complain or no. 取决于代码是什么,clang会抱怨或不抱怨。 If code is:
如果代码是:
cout << "Hello!";
return 0;
clang complains: clang抱怨:
error: constexpr function never produces a constant expression [-Winvalid-constexpr]
错误:constexpr函数永远不会产生常量表达式[-Winvalid-constexpr]
constexpr int main(int argc, char* argv[]) {
note: non-constexpr function 'operator<< >' cannot be used in a constant expression
注意:非constexpr函数'operator <<>'不能用于常量表达式
std::cout << "Hello!";
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:530:5: note: declared here
/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ostream:530:5:注意:在这里声明
operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
Fair enough, constexpr functions can't contain any cout statements, as we know. 很公平,constexpr函数不能包含任何cout语句,我们知道。 But what happens if we do this?
但是如果我们这样做会发生什么?
for (int i = 0; i < argc; i++)
std::cout << argv[i];
clang allows it! clang允许它! OK, but this can't possibly be a constexpr function even though it is marked constexpr, let's try to use it in constexpr context.
好吧,但这不可能是一个constexpr函数,即使它被标记为constexpr,让我们尝试在constexpr上下文中使用它。
int arr[foo::main(argc, argv)];
It works! 有用! So it must be clang bug?
那一定是clang bug? Reason I say clang because gcc complains:
我之所以说clang是因为gcc抱怨:
error: body of constexpr function 'constexpr int foo::main(int, char**)' not a return-statement
错误:constexpr函数的主体'constexpr int foo :: main(int,char **)'不是return语句
So my conclusion is clang is wrong and gcc is right. 所以我的结论是铿锵有误,而gcc是对的。
Clang is correct here. Clang在这里是正确的。
First example 第一个例子
Here, the code is: 这里的代码是:
constexpr int foo::main(int argc, char* argv[]) {
std::cout << argv[i];
return 0;
}
In C++11 , this code is ill-formed, because the body contains an expression-statement , which is not permitted in a constexpr
function definition. 在C ++ 11中 ,此代码格式错误,因为正文包含一个表达式语句 ,这在
constexpr
函数定义中是不允许的。
In C++1y , this code is ill-formed with no diagnostic required, because a call to foo::main
can never produce a constant expression (because it always calls operator<<(std::ostream&, const char*)
, which is not constexpr
). 在C ++ 1y中 ,此代码格式错误 ,无需诊断,因为对
foo::main
的调用永远不会产生常量表达式(因为它总是调用operator<<(std::ostream&, const char*)
,这不是constexpr
)。
Second example 第二个例子
In this case, the code is: 在这种情况下,代码是:
constexpr int foo::main(int argc, char* argv[]) {
for (int i = 0; i < argc; i++)
std::cout << argv[i];
return 0;
}
In C++11 , this code is ill-formed, because it contains a for
-statement. 在C ++ 11中 ,此代码格式不正确,因为它包含
for
statement。
In C++1y , this code is valid. 在C ++ 1y中 ,此代码有效。 In particular,
foo::main(0, 0)
is a constant expression (with value 0
). 特别是,
foo::main(0, 0)
是一个常量表达式(值为0
)。 Since foo::main
is usable in a constant expression, Clang is not permitted to reject it, and does not do so. 由于
foo::main
可用于常量表达式,因此不允许Clang拒绝它,也不允许拒绝它。
Third example 第三个例子
int arr[foo::main(argc, argv)];
The array bound here is not a constant expression (because it reads argc
and argv
, which are not constant). 这里绑定的数组不是常量表达式(因为它读取
argc
和argv
,它们不是常量)。 However, Clang supports variable-length arrays as an extension by default. 但是,Clang默认支持可变长度数组作为扩展。 You can specify
-pedantic-errors
to put clang into strictly-conforming mode, and in that mode it will reject this code. 您可以指定
-pedantic-errors
将clang置于严格一致的模式,并且在该模式下它将拒绝此代码。
GCC's diagnostic: 海湾合作委员会的诊断:
error: body of constexpr function 'constexpr int foo::main(int, char**)' not a return-statement
错误:constexpr函数的主体'constexpr int foo :: main(int,char **)'不是return语句
is incorrect in both C++11 and C++1y. 在C ++ 11和C ++ 1y中都是不正确的。 In C++11, it's incorrect because the rule is more subtle (the body of a
constexpr
function can contain typedef
s and a few other constructs, not just return
-statements). 在C ++ 11中,它是不正确的,因为规则更加微妙(
constexpr
函数的主体可以包含typedef
和一些其他结构,而不仅仅是return
-statements)。 In C++1y, the rule no longer exists at all. 在C ++ 1y中,规则根本不存在。
So gcc 4.8.1 does not implement relaxed constexpr restraints, but clang 3.5 does. 所以gcc 4.8.1没有实现轻松的constexpr限制,但是clang 3.5确实如此。 My mistake was that clang and gcc both have variable length array extensions.
我的错误是clang和gcc都有可变长度的数组扩展。 if I had used std::array instead, both compilers would reject the code.
如果我使用了std :: array,两个编译器都会拒绝代码。 What I still don't understand is if clang allows relaxed constexpr, then why is it not a constexpr?
我仍然不明白的是,如果clang允许放松constexpr,那么为什么它不是constexpr?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.