繁体   English   中英

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

[英]constexpr bug in clang but not in gcc?

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

#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;

clang抱怨:

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

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

注意:非constexpr函数'operator <<>'不能用于常量表达式

  std::cout << "Hello!"; 

/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) 

很公平,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 **)'不是return语句

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

Clang在这里是正确的。

第一个例子

这里的代码是:

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

在C ++ 11中 ,此代码格式错误,因为正文包含一个表达式语句 ,这在constexpr函数定义中是不允许的。

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

第二个例子

在这种情况下,代码是:

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

在C ++ 11中 ,此代码格式不正确,因为它包含for statement。

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

第三个例子

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

这里绑定的数组不是常量表达式(因为它读取argcargv ,它们不是常量)。 但是,Clang默认支持可变长度数组作为扩展。 您可以指定-pedantic-errors将clang置于严格一致的模式,并且在该模式下它将拒绝此代码。

海湾合作委员会的诊断:

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

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

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

看看介绍这些变化的N3652

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM