clang中的constexpr错误但不是gcc中的错误?

时间:2014-02-03 23:44:16

标签: c++ clang constexpr c++14

我们来看一个简单的例子:

#include <iostream>

namespace foo {
    constexpr int main(int argc, char* argv[]) {
      // code
    }
}

int main(int argc, char* argv[])
{
    return foo::main(argc, argv);
}

取决于代码是什么,clang会抱怨或不抱怨。如果代码是:

cout << "Hello!";
return 0;
克朗抱怨道:

  

错误:constexpr函数永远不会产生常量表达式   [-Winvalid-constexpr]

constexpr int main(int argc, char* argv[]) {
     

注意:非constexpr函数'运算符&lt;&lt; &GT;”   不能用于常量表达式

    std::cout << "Hello!";
     

/usr/lib/gcc/x86_64-linux-gnu/4.8 /../../../../包括/ C ++ / 4.8 / ostream的:530:5:   注意:在此声明

operator<<(basic_ostream<char, _Traits>& __out, const char* __s)

很明显,constexpr函数不能包含任何cout语句,我们知道。但是,如果我们这样做会发生什么?

  for (int i = 0; i < argc; i++)
    std::cout << argv[i];

clang允许它!好的,但这不可能是一个constexpr函数,即使它被标记为constexpr,让我们尝试在constexpr上下文中使用它。

int arr[foo::main(argc, argv)];

有效!那一定是cla​​ng bug?我之所以说clang是因为gcc抱怨:

  

错误:constexpr函数的主体'constexpr int foo :: main(int,   char **)'不是退货声明

所以我的结论是铿锵有误,而gcc是对的。

3 个答案:

答案 0 :(得分:10)

Clang在这里是正确的。

第一个例子

这里的代码是:

constexpr int foo::main(int argc, char* argv[]) {
  std::cout << argv[i];
  return 0;
}

在C ++ 11 中,此代码格式错误,因为正文包含表达式语句constexpr中不允许这样做功能定义。

在C ++ 1y 中,此代码格式错误,无需诊断,因为对foo::main的调用永远不会产生常量表达式(因为它总是调用{{1 },这不是operator<<(std::ostream&, const char*))。

第二个例子

在这种情况下,代码是:

constexpr

在C ++ 11 中,此代码格式错误,因为它包含constexpr int foo::main(int argc, char* argv[]) { for (int i = 0; i < argc; i++) std::cout << argv[i]; return 0; } - 语句。

在C ++ 1y 中,此代码有效。特别是,for是一个常量表达式(值foo::main(0, 0))。由于0可用于常量表达式,因此不允许Clang拒绝它,并且不会拒绝它。

第三个例子

foo::main

这里绑定的数组是 not 一个常量表达式(因为它读取int arr[foo::main(argc, argv)]; argc,它们不是常量)。但是,Clang默认支持可变长度数组作为扩展。您可以指定argv将clang置于严格一致的模式,在该模式下它将拒绝此代码。

海湾合作委员会的诊断:

  

错误:constexpr函数的主体'constexpr int foo :: main(int,char **)'不是返回语句

在C ++ 11和C ++ 1y中都是不正确的。在C ++ 11中,它是不正确的,因为规则更加微妙(-pedantic-errors函数的主体可以包含constexpr s和一些其他结构,而不仅仅是typedef - 语句)。在C ++ 1y中,规则根本不存在。

答案 1 :(得分:2)

您在C ++ 1y模式下编译代码,其中包含放宽constexpr限制的措辞,包括所有循环语句。

查看引入这些更改的N3652

答案 2 :(得分:0)

所以gcc 4.8.1没有实现轻松的constexpr限制,但是clang 3.5确实如此。我的错误是clang和gcc都有可变长度的数组扩展。如果我使用了std :: array,两个编译器都会拒绝代码。我仍然不明白的是,如果clang允许放松constexpr,那么为什么它不是constexpr?