问题描述
以下一段代码在clang ++ 3.7.0下编译,但被g ++ 5.3.1拒绝。两者都有 -std = c ++ 14
选项。哪个编译器是正确的?任何人都知道标准会在哪里谈论这个?谢谢。
#include
使用namespace std;
constexpr int f(int n){
if(n 返回1;
int main(){
char k [f(1)];
}
输出
<$ p在函数'constexpr int f(int)'中:
c.cpp:code> [隐藏] 7:1:error:expression'< throw-expression>'不是常量表达式
}
^
[hidden] clang ++ -std = c ++ 14 c.cpp
[隐藏]
[隐藏] g ++ -v
使用内置规格。
COLLECT_GCC = / usr / bin / g ++
COLLECT_LTO_WRAPPER = / usr / libexec / gcc / x86_64-redhat-linux / 5.3.1 / lto-wrapper
目标:x86_64-redhat-linux
配置为:../configure --enable-bootstrap --enable-languages = c,c ++,objc,obj-c ++,fortran,ada,go,lto --prefix = / usr --mandir = / usr / share / man --infodir = / usr / share / info --with-bugurl = http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads = posix --enable-checking = release --enable-multilib --with-system-zlib --enable -__ cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash- style = gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune = generic --with- arch_32 = i686 --build = x86_64-redhat-linux
线程模型:posix
gcc版本5.3.1 20151207(Red Hat 5.3.1-2)(GCC)
[hidden]
[hidden] clang ++ -v
铿锵声3.7.0版(http://llvm.org/git/clang.git 2ddd3734f32e39e793550b282d44fd71736 f8d21)
目标:x86_64-unknown-linux-gnu
线程模型:posix
找到候选GCC安装:/usr/lib/gcc/x86_64-redhat-linux/3.4.6
找到候选GCC安装:/usr/lib/gcc/x86_64-redhat-linux/5.3.1
选定的GCC安装:/usr/lib/gcc/x86_64-redhat-linux/5.3.1
候选multilib:。; @ m64
候选multilib:32; @ m32
所选multilib:。; @ m64
clang是正确的,请注意也接受此代码。这是一个格式良好的constexpr函数,只要参数的值能让函数被评估为核心常量表达式。在你的情况下, 1
就是这样一个值。
这在C ++ 14标准部分草案 7.1.5
constexpr说明符[dcl.constexpr]告诉我们在constexpr函数中允许什么:
对 throw
没有限制, em>强调我的):
以下的段落中,我们有以下例子,类似于你:
constexpr int f(bool b)
{return b?抛出0:0; } //确定
constexpr int f(){return f(true); } //不合格,不需要诊断
throw
5.19 [expr.const] 中的核心常量表达式中包含$ c> 不允许段落 2
其中说:
,并包含以下项目符号:
等 f
在核心常量表达式中不可用当 n 。
更新
b
正如TemplateRex所指出的,有两个gcc bug报告:
- .cgi?id = 66026rel =noreferrer> C ++ 14] throw-expression不是一个有效的常量表达式
TemplateRex也注意到这些修补程序不适用于 5.3.0
,并且只在trunk中。不,提供解决方法。
The following piece of code compiles under clang++ 3.7.0 but is denied by g++ 5.3.1. Both have -std=c++14
option. Which compiler is correct? Anyone knows where in the standard talks about this? Thanks.
#include <stdexcept>
using namespace std;
constexpr int f(int n) {
if (n <= 0) throw runtime_error("");
return 1;
}
int main() {
char k[f(1)];
}
Output
[hidden] g++ -std=c++14 c.cpp
c.cpp: In function ‘constexpr int f(int)’:
c.cpp:7:1: error: expression ‘<throw-expression>’ is not a constant-expression
}
^
[hidden] clang++ -std=c++14 c.cpp
[hidden]
[hidden] g++ -v
Using built-in specs.
COLLECT_GCC=/usr/bin/g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/5.3.1/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --enable-bootstrap --enable-languages=c,c++,objc,obj-c++,fortran,ada,go,lto --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-shared --enable-threads=posix --enable-checking=release --enable-multilib --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-plugin --enable-initfini-array --disable-libgcj --with-isl --enable-libmpx --enable-gnu-indirect-function --with-tune=generic --with-arch_32=i686 --build=x86_64-redhat-linux
Thread model: posix
gcc version 5.3.1 20151207 (Red Hat 5.3.1-2) (GCC)
[hidden]
[hidden] clang++ -v
clang version 3.7.0 (http://llvm.org/git/clang.git 2ddd3734f32e39e793550b282d44fd71736f8d21)
Target: x86_64-unknown-linux-gnu
Thread model: posix
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/3.4.6
Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/5.3.1
Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/5.3.1
Candidate multilib: .;@m64
Candidate multilib: 32;@m32
Selected multilib: .;@m64
解决方案 clang is correct, note the HEAD revision of gcc accepts also accepts this code. This is a well-formed constexpr function, as long as there is value for the argument(s) that allows the function to be evaluated as a core constant expression. In your case 1
is such a value.
This is covered in the draft C++14 standard section 7.1.5
The constexpr specifier [dcl.constexpr] which tells us what is allowed in a constexpr function:
no restriction on throw
and it also says (emphasis mine):
and below this paragraph we have the following example, similar to yours:
constexpr int f(bool b)
{ return b ? throw 0 : 0; } // OK
constexpr int f() { return f(true); } // ill-formed, no diagnostic required
throw
is not allowed in a core constant expression, which is covered in section 5.19
[expr.const] paragraph 2
which says:
and includes the following bullet:
and so f
would not be usable in a core constant expression when n <= 0
.
Update
As TemplateRex points out, there are two gcc bugs reports for this:
- Never executed "throw" in constexpr function fails to compile
- C++14] throw-expression is not a valid constant-expression
TemplateRex also notes the fixes are not applied to to 5.3.0
and are only in trunk. No, work arounds are provided.
这篇关于投入constexpr函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!