2015-11-05 9 views
6

Próbuję napisać CRTP, aby zawierać static constexpr typu pochodnego, ponieważ nie można tego zrobić z tylko jedną klasą. Ten kod kompiluje się dobrze w GCC, ale clang narzeka, że ​​Derived jest niekompletnym typem. Który jest poprawny?Czy definicja klasy jest kompletna, gdy jest przekazywana do klasy bazowej?

template<class T> 
class Base { 
public: 
    static constexpr T a = T(1), b = T(20); 
}; 

class Derived : public Base<Derived> { 
public: 
    int x; 
    constexpr Derived(int x) : x(x) {} 
}; 
+1

Bądź ostrożny przy konstruktorze Derived, lokalna zmienna x, a element członkowski ma tę samą nazwę. – Brahim

+0

Chcę tylko podkreślić, że zachowanie obiektów pochodnych jako statycznych wewnątrz klasy bazowej nie jest najlepszym pomysłem .. –

+0

Jedynym powodem, dla którego to zrobiono w ten sposób, ponieważ nie mogę wstawić 'static constexpr' typu' Derived' do 'Derived'. Chciałem to zrobić: 'Derived :: a' zamiast czegoś takiego jak' Derived :: constants :: a'. – user975989

Odpowiedz

2

Derived jest niepełny w punkcie, w którym jest tworzony Base<Derived> ([class.mem]/2), co zdarza się w prawo podczas rozdzielczości. Użyto constexpr, który wymaga inicjalizatora zgodnie z [class.static.data]/3, a kiedy Base<Derived> jest instancjonowany, podobnie deklaracje jego statycznych elementów danych ([temp.inst]/3), które zawierają inicjatory. Jednak inicjatorzy próbują stworzyć obiekt niekompletnego typu, który jest źle sformułowany.

można zadeklarować jako członek const zamiast:

template<class T> 
class Base { 
public: 
    static const T a; 
}; 
template <typename T> 
constexpr T Base<T>::a = T(1); 

od inicjatora jest teraz w definicji tej instancji inicjatora może być odroczone do czasu np Derived jest kompletny. Demo z Clang.

Należy pamiętać, że Clang jeszcze nie traktuje a jako constexpr, ponieważ nie potrafi szybko utworzyć jego definicji. Zobacz błąd #24541.

+0

Ale wtedy nie można zrobić 'static_assert (Derived :: ax == 1," ")', który w rodzaju pokonuje cel 'constexpr'. – user975989

+0

@ user975989 To wydaje się być błędem Clang. – Columbo

+0

@ user975989 Znaleziono DR i dodał go do odpowiedzi. (Zabawnie, użyty przykład jest bardzo ważny!) – Columbo

Powiązane problemy