2017-10-18 87 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確實是包含成員的類的基礎,所以應該定義行爲,並且構造函數調用常量表達式。