2017-10-18 27 views
11

Natknąłem się na problem z g ++ z upcastingiem wskaźnika członkowskiego w kontekście constexpr przy użyciu static_cast. Zobacz przykład kodu.static_cast wskaźnika elementu w kontekście constexpr na g ++

Podczas kompilacji za pomocą g ++ wersji 6.3 i 7.0 generują błąd kompilacji, mówiąc, że reinterpret_cast nie jest wyrażeniem stałym. Podczas gdy wersja 4.0 języka klang nie daje żadnego błędu, co uważam za poprawne, ponieważ nie ma tutaj reinterpret_cast.

Czy to błąd w g ++ lub clang? Jakie jest prawidłowe zachowanie?

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); 

Compiler wyjście

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

To naprawdę nie jest upcast. –

Odpowiedz

3

GCC przypuszczalnie misapprehends [expr.static.cast]/12, który pozwala na swoją obsadę i zauważa, że ​​

Jeśli klasa B zawiera oryginalnego elementu, lub jest podstawą lub klasa pochodzi od klasa zawierająca oryginalny element, wynikowy wskaźnik do punktów członka do pierwotnego elementu. W przeciwnym razie zachowanie jest niezdefiniowane.

Od Base jest rzeczywiście podstawą klasy zawierającej element, zachowanie powinno zostać zdefiniowane, a konstruktor wywołać stałe wyrażenie.