2015-04-03 4 views
18

Я пытаюсь скомпилировать этот код, но g ++ жалуется на ZERO с неполным типом. Означает ли это, что в C++ структура не может содержать экземпляр static constexpr? Если да, то почему?C++ static constexpr field с неполным типом

struct Cursor 
{ 
    size_t row,column; 

    static constexpr Cursor ZERO {0,0}; 
    //error: constexpr const Cursor Cursor::ZERO has incomplete type 
}; 

EDIT: Я понимаю, что Cursor не может иметь полный вид, когда я объявляю ZERO. Я хотел бы знать: есть ли у меня способ ZERO, принадлежащий Cursor и до сих пор являющийся constexpr?

+0

могли бы вы предоставить сообщение об ошибке? –

+2

Я подозреваю, что это из-за constexpr & inline инициализации. – Quentin

+0

Переместите инициализацию вне объявления класса. –

ответ

12

К сожалению, вы просто не можете этого сделать!

Некоторых static constexpr элементы могут быть инициализированы инлайн:

[C++11 9.4.2/3]:[..] Член static данные буквального типа может быть объявлен в определении класса с constexpr спецификатором; если это так, в его декларации указывается скобка-равный-инициализатор, в котором каждый параметр-инициализатор, являющийся присваиванием-выражением является постоянным выражением. [..]

Cursor является буквальным типа, так что это имеет значение.

А использование самого Cursor в качестве члена static данных в пределах своего типа не является проблемой, до тех пор, как вы отформатируйте ее в лексической области видимости пространства имен:

[C++11: 9.4.2/2]:Декларации члена в static данных в определении его класса не является определением и может быть неполным типом, отличным от vv. Определение для элемента данных static должно появляться в области пространства имен, охватывающей определение класса участника. В определении в области пространства имен имя элемента данных static должно быть квалифицировано по его имени класса с использованием оператора ::. Инициализатор выражение в определении элемента данных static относится к сфере его класса (3.3.7).

Но вы не можете сделать это с constexpr:

[C++11: 7.1.5/9]:constexpr спецификатор используется в объявлении объекта объявляет объект как const. Такой объект должен иметь буквальный тип и должен быть инициализирован. [..]

Я думаю, что все эти формулировки можно было бы улучшить, но, в то же время, я думаю, что вы будете иметь, чтобы сделать ZERO не-членов в пространстве имен объемлющего.

+2

Спасибо за этот полный ответ. Учитывая, что курсор фактически определен внутри класса VGA, я просто сделаю ZERO статическим элементом constexpr VGA. Иногда я нахожу определенное ограничение довольно раздражающим ... – lodo

5

Есть ли способ, который может иметь ZERO, принадлежащий курсору, и все еще являющийся constexpr?

Да, если считать вложенные подклассы, как «принадлежность к» содержащий класс:

struct Cursor 
{ 
    size_t row,column; 

    struct Constants; 
}; 

struct Cursor::Constants 
{ 
    static constexpr Cursor ZERO {0,0}; 
}; 
3

Вы можете, если вы согласны иметь функцию, а не переменная

struct Cursor 
{ 
    size_t row,column; 

    static constexpr Cursor ZERO() { return Cursor{0,0}; } 
}; 
Смежные вопросы