2012-03-31 7 views
16

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

nullptr_t n; 

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

+0

Я думал, что вы должны обрабатывать 'nullptr_t' как обычный тип указателя, то есть не как класс. Поэтому я предполагаю, что 'nullptr_t n;' создает переменную _uninitialised_; вы предполагаете, что явно пишите 'nullptr_t n = nullptr;'. Но у меня нет компилятора C++ 11, поэтому я не могу проверить. И я не могу найти, где я прочитал его в формальных спецификациях ... –

+0

FWIW, clang принимает «nullptr_t n;» Вот. –

ответ

17

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

Стандарт говорит (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.

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

  • По умолчанию инициализация (nullptr_t n;), который оставляет значение n undefined. Как правильно указал Йоханнес Шауб, это прекрасно компилируется с новейшей версией Clang.
  • Значение инициализация (nullptr_t n = nullptr_t();), который инициализирует п 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. [...] Константа нулевого указателя интегрального типа может быть преобразована в prvalue типа 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

Вы делаете ошибку, обобщая что-то, что относится к классам, к неклассам. Неклассы не имеют каких-либо функций-членов. –

+1

Типы неклассов могут быть построены по умолчанию без функции-члена. Речь идет не о наличии конструктора по умолчанию в смысле наличия функции-члена, а в смысле выполнения концепции построчного по умолчанию типа. – ComicSansMS

+0

Из стандарта: «Тип, для которого nullptr_t является синонимом, имеет характеристики, описанные в пунктах 3.9.1 и 4.10». Перейдите в раздел 3.9.1 («Основные типы») и узнайте, что вы можете объявлять переменные типа int-typed, float-typed, действительно, nullptr_t. –

1

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

typedef decltype(nullptr) nullptr_t; 

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

См. Также here.

+0

Я думаю, что спецификация, говорящая о значениях nullptr_t в разделе «Основные типы», подразумевает, что nullptr_t является фундаментальным типом. Нет явного списка того, какие типы являются фундаментальными типами, что означает, что нужно собрать их, итерации по всем типам, упомянутым в «Основные типы». И в любом случае имеет смысл, что это фундаментальный тип. –

+4

Обратите внимание, что вы не можете сказать: «Тип nullptr_t - это библиотека typedef». Typedef делает * not * вводит новый тип. Он просто создает псевдоним существующего типа. Тип, который «nullptr_t» имеет псевдонимы *, вводится языком. –

+0

@ JohannesSchaub-litb - ОК, отредактировал вопрос, чтобы сделать этот пункт более понятным. Эта точка заключается в том, что тип «nullptr» не имеет имени или псевдонима в программе на C++ до тех пор, пока не будет назначен псевдоним (лучше всего использовать стандартный файл заголовка библиотеки). –

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

  • Нет связанных вопросов^_^