constexpr(但不是真的)构造函数在gcc中编译,但不在clang中编译

时间:2018-02-22 20:47:44

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

我在C ++ 14及以上版本中使用import {Provider} from 'react-redux'; const createMockStore = (getState) => { const middlewares = []; return configureStore(middlewares)(getState); }; const store = createMockStore(); const component = renderIntoDocument( <Provider store={store}> <LoginContainer /> </Provider> ); 构造函数,并注意到一些奇怪的东西。这是我的代码:

constexpr

足够简单的例子。我用#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; } 编译它,期望它给我一个编译错误(因为我使用g++ -std=c++14 -o cx_test cx_test.cpp和流操作符来打印函数的名称。但是,令我惊讶的是,它编译了!当我跑它,它给出了以下输出:

cout

但是,当我用clang编译时,我得到:

$> 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()
$>

这似乎是g ++的一个错误,因为构造函数似乎违反了$> 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. $> 的限制,但我不太确定。哪个编译器是正确的?

Here是g ++版本,here是clang版本(在ideone上)。

1 个答案:

答案 0 :(得分:6)

gcc和clang都是正确的,您的程序格式不正确,不需要进行诊断,因为无法调用构造函数,因此可以将它们构造为核心常量表达式的子表达式。

来自[dcl.constexpr]p5

  

对于非模板,非默认constexpr函数或   非模板,非默认,非继承constexpr构造函数,如果   不存在任何参数值,因此无法调用该函数或   构造函数可以是核心常量的评估子表达式   表达式([expr.const]),程序格式错误;没有诊断   必填。 [示例:

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的诊断信息(see it live):

{ constexpr A a; }