2017-10-18 89 views
11

我遇到了一个g ++问题,使用static_cast在constexpr上下文中上传了一个成员指针。看代码示例。static_cast成员指针在g ++上的constexpr上下文中

当使用g ++版本6.3和7.0进行编译时,他们给出编译错误,说reinterpret_cast不是一个常量表达式。 虽然铛4.0版没有提供任何错误,我认为这是正确的,因为这里没有reinterpret_cast。

这是g ++或clang中的错误吗?什么是正确的行为?

struct Base {}; 

struct Derived : Base 
{ 
    int i; 
}; 

struct Ptr 
{ 
    constexpr Ptr(int Derived::* p) : p(static_cast<int Base::*>(p)){} 
    int Base::* p; 
}; 

constexpr Ptr constexpr_ptr(&Derived::i); 

编译器输出

g++ -c -std=c++14 test.cpp 
test.cpp:17:40: in constexpr expansion of ‘Ptr(&Derived::i)’ 
test.cpp:11:41: error: a reinterpret_cast is not a constant expression 
constexpr Ptr(int Derived::* p) : p(static_cast<int Base::*>(p)){} 
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+1

这不是一个真正的upcast。 –

回答

3

GCC想必误解了[expr.static.cast]/12,允许你的铸造,并注意到

如果类B包含原始部件,或者是碱或派生类的包含原始成员的类,生成的指向成员的指针指向原始成员。否则,行为是不确定的。

因为Base确实是包含成员的类的基础,所以应该定义行为,并且构造函数调用常量表达式。