cal*_*ter 5 c++ gcc clang constexpr c++14
我正在玩constexprC++ 14及以上版本的构造函数,并注意到一些奇怪的东西.这是我的代码:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
#define PFN(x) cout << x << __PRETTY_FUNCTION__ << endl
#define PF PFN("")
#define NL cout << endl
struct A {
constexpr A() { PF; }
virtual ~A() { PF; NL; }
};
struct B : A {
constexpr B() { PFN(" "); }
virtual ~B() { PFN(" "); }
};
int main(int argc, char** argv) {
{ A a; }
{ B b; }
A* a = new B;
delete a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
足够简单的例子.我编译它g++ -std=c++14 -o cx_test cx_test.cpp,期望它给我一个编译错误(因为我使用cout和流操作符来打印函数的名称.但是,令我惊讶的是,它编译!当我运行它时,它给出了以下输出:
$> g++ -std=c++14 -o cx_test cx_test.cpp && ./cx_test
constexpr A::A()
virtual A::~A()
constexpr A::A()
constexpr B::B()
virtual B::~B()
virtual A::~A()
constexpr A::A()
constexpr B::B()
virtual B::~B()
virtual A::~A()
$>
Run Code Online (Sandbox Code Playgroud)
但是,当我用clang编译时,我得到:
$> clang++ -std=c++14 -o cx_test cx_test.cpp && ./cx_test
cx_test.cpp:12:15: error: constexpr constructor never produces a constant expression [-Winvalid-constexpr]
constexpr A() { PF; }
^
cx_test.cpp:12:21: note: non-constexpr function 'operator<<<std::char_traits<char> >' cannot be used in a constant expression
constexpr A() { PF; }
^
cx_test.cpp:9:12: note: expanded from macro 'PF'
#define PF PFN("")
^
cx_test.cpp:8:26: note: expanded from macro 'PFN'
#define PFN(x) cout << x << __PRETTY_FUNCTION__ << endl
^
/usr/bin/../lib/gcc/x86_64-linux-gnu/6.3.0/../../../../include/c++/6.3.0/ostream:556:5: note: declared here
operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
^
1 error generated.
$>
Run Code Online (Sandbox Code Playgroud)
这似乎是g ++的一个错误,因为构造函数似乎违反了限制constexpr,但我不太确定.哪个编译器正确?
gcc和clang都是正确的,你的程序格式错误,不需要诊断,因为无法调用构造函数,因此可以将它们作为核心常量表达式的子表达式进行求值.
对于非模板,非默认的constexpr函数或非模板,非默认的,非继承的constexpr构造函数,如果不存在参数值,则调用函数或构造函数可以是核心常量的计算子表达式表达式([expr.const]),程序不正确; 无需诊断.[例如:
Run Code Online (Sandbox Code Playgroud)constexpr int f(bool b) { return b ? throw 0 : 0; } // OK constexpr int f() { return f(true); } // ill-formed, no diagnostic required struct B { constexpr B(int x) : i(0) { } // x is unused int i; }; int global; struct D : B { constexpr D() : B(global) { } // ill-formed, no diagnostic required // lvalue-to-rvalue conversion on non-constant global };- 结束例子]
如果我们强制在常量表达式上下文中评估构造函数,那么您也将从gcc接收诊断(请参见实时):
{ constexpr A a; }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
405 次 |
| 最近记录: |