Является ли nullptr_t конструктивным типом по умолчанию? - PullRequest
16 голосов
/ 31 марта 2012

Я не могу сказать по стандарту C ++ 11, имеет ли nullptr_t конструктор по умолчанию. Другими словами, допустимо ли следующее:

nullptr_t n; 

GCC и VC ++ разрешают приведенный выше код, но clang - нет. Я не могу найти ничего в Стандарте, указывающем, что у него нет конструктора по умолчанию, и то, что я могу найти, предполагает, что он должен. Это важно для меня, потому что я пишу базовую альтернативную реализацию nullptr для поддержки старых компиляторов, и мне нужно знать, нужно ли мне предоставить ему конструктор по умолчанию.

Ответы [ 2 ]

17 голосов
/ 31 марта 2012

Что говорит Стандарт

Стандарт гласит (18,2)

nullptr_t определяется следующим образом:

namespace std {
   typedef decltype(nullptr) nullptr_t;
}

Тип, для которого nullptr_t является синонимом, имеет характеристики, описанные в 3.9.1 и 4,10.

Где 3.9.1 в основном говорит, что он должен быть того же размера, что и void*, а 4.10 определяет правила преобразования для nullptr.

Редактировать: 3.9.9, кроме того, прямо указано, что nullptr_t является скалярным типом, что означает применение ожидаемых правил инициализации для встроенных типов из 8.5:

  • Инициализация по умолчанию (nullptr_t n;), которая оставляет значение n неопределенным. Как правильно заметил Йоханнес Шауб, это прекрасно сочетается с новейшей версией Clang.
  • Значение-инициализация (nullptr_t n = nullptr_t();), которая инициализирует n до 0.

Это поведение идентично, например, int, таким образом, nullptr_t определенно является конструируемым по умолчанию. Интересный вопрос здесь: что означает для nullptr_t неопределенное значение? В конце дня есть только одно значимое возможное значение для nullptr_t, которое составляет nullptr. Кроме того, сам тип определяется только через семантику литерала nullptr. Применяется ли эта семантика к унитизированному значению?

Почему этот вопрос не имеет значения на практике

Вы не хотите объявлять новую переменную типа nullptr_t. Единственная значимая семантика этого типа уже выражена через литерал nullptr, поэтому всякий раз, когда вы будете использовать свою пользовательскую переменную типа nullptr_t, вы также можете использовать nullptr.

Что имеет значение на практике

Единственное исключение из этого заключается в том, что вы можете принимать нетипизированные параметры шаблона типа nullptr_t. Для этого случая полезно знать, какие значения можно преобразовать в nullptr_t, что описано в 4.10:

Константа нулевого указателя - это целочисленное константное выражение (5.19) prvalue целочисленного типа с нулевым значением или prvalue типа std::nullptr_t. [...] Константа нулевого указателя целочисленного типа может быть преобразована в значение типа std::nullptr_t.

Что в основном делает то, что вы ожидаете: вы можете написать

nullptr_t n = 0;    // correct: 0 is special

но не

nullptr_t n = 42;   // WRONG can't convert int to nullptr_t

И gcc 4.6, и Clang SVN понимают это правильно.

1 голос
/ 31 марта 2012

Хотя nullptr является новым дополнением к самому языку, std::nullptr_t является просто псевдонимом безымянного типа, псевдоним, объявленный в cstddef, выглядит так:

typedef decltype(nullptr) nullptr_t;

Хотя nullptr_t, будучи typedef, а не ключевым словом языка, не указан в качестве основного типа, он определен для поведения в качестве основного типа (а не, например, в качестве типа указателя или типа класса).Поэтому у него нет конструктора по умолчанию, но вы все равно можете объявить переменную, как вы это сделали.Ваша переменная не инициализирована, и мне интересно, как ее можно использовать и какое именно сообщение об ошибке вы получили от clang.

См. Также здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...