2015-11-05 5 views
6

Я пытаюсь написать CRTP, чтобы содержать static constexpr производного типа, поскольку это невозможно сделать только с одним классом. Этот код компилируется в GCC, но clang жалуется, что Derived является неполным типом. Какой из них прав?Является ли определение класса полным, когда оно передается базовому классу?

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

Будьте осторожны в конструкторе Derived, локальная переменная x и член имеют одно и то же имя. – Brahim

+0

Я просто хочу указать, что сохранение производных объектов как статических внутри базового класса - не самая лучшая идея .. –

+0

Единственная причина для этого это потому, что я не могу поставить 'static constexpr' типа' Derived' в 'Derived'. Я хотел бы сделать это: 'Derived :: a' вместо того, что-то вроде' Derived :: constants :: a'. – user975989

ответ

2

Derived является неполным в точке, в которой Base<Derived> создаетсе ([class.mem]/2), которое происходит сразу во время определения. Вы использовали constexpr, что требует инициализатора в соответствии с [class.static.data]/3, и когда создается экземпляр Base<Derived>, также объявляются его статические элементы данных ([temp.inst]/3), который включает инициализаторы. Однако инициализаторы пытаются создать объект неполного типа, который плохо сформирован.

Вы можете объявить элемент, как const вместо:

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

поскольку инициализатор теперь в определении, то конкретизация этого инициализатора не может быть отложено до тех пор, например, Derived завершен. Demo с Clang.

Обратите внимание, что Кланг еще не обрабатывает a как constexpr, потому что он не может запрограммировать его определение. См. Ошибку #24541.

+0

Но тогда вы не можете сделать 'static_assert (Derived :: ax == 1," ")', что поражает цель 'constexpr'. – user975989

+0

@ user975989 Это похоже на ошибку Clang. – Columbo

+0

@ user975989 Нашел DR и добавил его к ответу. (Как ни странно, пример используется очень много!) – Columbo

Смежные вопросы