对于 C++17,__cplusplus 的值是多少?
What is the value of __cplusplus for C++17?
我们正在尝试在 C++17 及其 下测试一些代码。我似乎无法让 GCC 提供 __cplusplus
:
的值
$ /opt/local/bin/g++ -std=c++17 -dM -E - </dev/null | grep __cplusplus
cc1: warning: command line option '-std=c++1z' is valid for C++/ObjC++ but not for C
$
并且:
$ /opt/local/bin/g++ --version
g++-mp-6 (MacPorts gcc6 6.1.0_0) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
使用 C++17 时 __cplusplus
的值是多少?
tl;dr:对于 C++17,__cplusplus
是 201703L
。
What is the value of __cplusplus
when using C++17?
根据标准草案N4594 §16.8/p1 预定义宏名称[cpp.predefined] (Emphasis Mine):
The following macro names shall be defined by the implementation:
__cplusplus
The name __cplusplus
is defined to the value
201402L when compiling a C++ translation unit.156
156) It is intended that future versions of this standard will
replace the value of this macro with a greater value. Non-conforming
compilers should use a value with at most five decimal digits.
然而,为 C++14 标准指定了相同的值。显然看起来是这样,还没有为 C++17 标准设置 official/standard __cplusplus
值。
在 GCC 版本 6.1 和 7.0 中,该值更改为 201500
在 Clang 版本 3.8 和 3.9 中该值未更改 201406.
因此,您需要稍等片刻才能看到标准值。
---更新---
根据 C++ 标准 §19.8/p1 预定义的宏名称 [cpp.predefined](Emphasis Mine):
1 The following macro names shall be defined by the
implementation:
__cplusplus
The integer literal 201703L.
因此,使用C++17时__cplusplus
的值应为201703L.
我真的不知道为什么 __cplusplus
没有显示为常规宏,但我猜这是因为您无法重新定义它。这就是我确定其价值的方式。
#include <iostream>
int main( int argc, char** argv )
{
std::cout << __cplusplus << std::endl;
return 0;
}
然后编译显示值。
$ g++-6 test.cpp && ./a.out
201402
$ g++-6 -std=c++17 test.cpp && ./a.out
201500
我会检查它是否是 >= 201500
,而不是检查任何特定值。
我会尝试:
#if __cplusplus > 201402L
// C++14 code here
...
#endif
换句话说,随着编译器添加更多功能,对大于 C++14 的测试应该会起作用。正如上面有人提到的,GCC 使用 201500L
。看起来 clang 使用 201406L
(我猜是在 C++14 之后四个月)。
使用上面的代码片段应该是跨平台的,即使在 C++17 对 __cplusplus
具有实际价值时也能正常工作。有关不断发展的功能的更多详细信息,请尝试 feature test macros.
我知道你问这个问题时引用了你正在使用的 Gnu C++ 编译器,但你可能想对 Visual C++ 编译器上发生的事情有一些了解,严格来说,你的问题并没有询问特定的编译器。
目前,截至本文发布之日,VC++ 2017 编译器将 __cplusplus
设置为 199711L
,而不是您将编译器设置为使用时所期望的c++17.
要使其正确报告,您还必须设置 /Zc:__cplusplus
。
(来源:https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017)
至于为什么?好吧……用他们的话来说:
We tried updating the macro by default and discovered that a lot of
code doesn’t compile correctly when we change the value of
__cplusplus.
(来源:https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/)
通常你应该使用 __cplusplus
define 来检测 c++17,但默认情况下微软编译器没有正确定义那个宏,见 https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - 你需要修改项目设置以包含/Zc:__cplusplus
开关,或者你可以使用这样的语法:
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
//C++17 specific stuff here
#endif
现代编译时检查,您可以放入任何需要它的文件:
static_assert(__cplusplus >= 201703L, "This file expects a C++17 compatible compiler.");
我们正在尝试在 C++17 及其 __cplusplus
:
$ /opt/local/bin/g++ -std=c++17 -dM -E - </dev/null | grep __cplusplus
cc1: warning: command line option '-std=c++1z' is valid for C++/ObjC++ but not for C
$
并且:
$ /opt/local/bin/g++ --version
g++-mp-6 (MacPorts gcc6 6.1.0_0) 6.1.0
Copyright (C) 2016 Free Software Foundation, Inc.
使用 C++17 时 __cplusplus
的值是多少?
tl;dr:对于 C++17,__cplusplus
是 201703L
。
What is the value of
__cplusplus
when using C++17?
根据标准草案N4594 §16.8/p1 预定义宏名称[cpp.predefined] (Emphasis Mine):
The following macro names shall be defined by the implementation:
__cplusplus
The name__cplusplus
is defined to the value 201402L when compiling a C++ translation unit.156156) It is intended that future versions of this standard will replace the value of this macro with a greater value. Non-conforming compilers should use a value with at most five decimal digits.
然而,为 C++14 标准指定了相同的值。显然看起来是这样,还没有为 C++17 标准设置 official/standard __cplusplus
值。
在 GCC 版本 6.1 和 7.0 中,该值更改为 201500
在 Clang 版本 3.8 和 3.9 中该值未更改 201406.
因此,您需要稍等片刻才能看到标准值。
---更新---
根据 C++ 标准 §19.8/p1 预定义的宏名称 [cpp.predefined](Emphasis Mine):
1 The following macro names shall be defined by the implementation:
__cplusplus
The integer literal 201703L.
因此,使用C++17时__cplusplus
的值应为201703L.
我真的不知道为什么 __cplusplus
没有显示为常规宏,但我猜这是因为您无法重新定义它。这就是我确定其价值的方式。
#include <iostream>
int main( int argc, char** argv )
{
std::cout << __cplusplus << std::endl;
return 0;
}
然后编译显示值。
$ g++-6 test.cpp && ./a.out
201402
$ g++-6 -std=c++17 test.cpp && ./a.out
201500
我会检查它是否是 >= 201500
,而不是检查任何特定值。
我会尝试:
#if __cplusplus > 201402L
// C++14 code here
...
#endif
换句话说,随着编译器添加更多功能,对大于 C++14 的测试应该会起作用。正如上面有人提到的,GCC 使用 201500L
。看起来 clang 使用 201406L
(我猜是在 C++14 之后四个月)。
使用上面的代码片段应该是跨平台的,即使在 C++17 对 __cplusplus
具有实际价值时也能正常工作。有关不断发展的功能的更多详细信息,请尝试 feature test macros.
我知道你问这个问题时引用了你正在使用的 Gnu C++ 编译器,但你可能想对 Visual C++ 编译器上发生的事情有一些了解,严格来说,你的问题并没有询问特定的编译器。
目前,截至本文发布之日,VC++ 2017 编译器将 __cplusplus
设置为 199711L
,而不是您将编译器设置为使用时所期望的c++17.
要使其正确报告,您还必须设置 /Zc:__cplusplus
。
(来源:https://docs.microsoft.com/en-us/cpp/build/reference/zc-cplusplus?view=vs-2017)
至于为什么?好吧……用他们的话来说:
We tried updating the macro by default and discovered that a lot of code doesn’t compile correctly when we change the value of __cplusplus.
(来源:https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/)
通常你应该使用 __cplusplus
define 来检测 c++17,但默认情况下微软编译器没有正确定义那个宏,见 https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/ - 你需要修改项目设置以包含/Zc:__cplusplus
开关,或者你可以使用这样的语法:
#if ((defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) || __cplusplus >= 201703L)
//C++17 specific stuff here
#endif
现代编译时检查,您可以放入任何需要它的文件:
static_assert(__cplusplus >= 201703L, "This file expects a C++17 compatible compiler.");