Подтвердить что ты не робот

Статическое поле constexpr С++ с неполным типом

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

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?

4b9b3361

Ответ 1

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

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

[C++11 9.4.2/3]: [..] A static член данных типа literal может быть объявлен в определении класса с помощью спецификатора 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

есть ли способ, которым я могу иметь 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}; }
};