Почему & quot; bool c = nullptr; & quot; компилирует (C ++ 11)?

Я не понимаю, почему следующий код компилирует ?

int main()
{
//int a = nullptr;  // Doesn't Compile
//char b = nullptr; // Doesn't Compile
bool c = nullptr; // Compiles

return 0;
}

в то время как прокомментированный раздел не.


Я уже прошел этот а также этот.

И то и другое bool а также nullptr являются ключевыми словами, так что же уникального в других типах данных?

27

Решение

По той же причине, что и

if( p ) { ... }

компилирует: любое значение базового типа неявно преобразуется в логическое, с 0 преобразование в false и любое другое значение для true,

Первоначально базовые значения типа должны были быть преобразованы в bool для совместимости с. С изначально не было bool тип, но любое числовое выражение может быть использовано как логическое (с 0 == false конвенции). И теперь мы попали в путаницу обратной совместимости. nullptr должен поддерживать идиоматические конструкции, такие как if(p)особенно для случаев, когда буквальный код старого кода 0 или же NULL заменяется на nullptr, Например. код как if(p) может быть результатом расширения макроса или в коде шаблона.


добавление: технический как почему nullptr не конвертируется, например, в int,

поскольку nullptr неявно преобразуется в bool, а также bool (к сожалению) неявно преобразуется в intможно было ожидать, что nullptr следует также преобразовать в int, Но точка nullptr является то, что он должен вести себя как значение указателя. И хотя указатели неявно преобразуются в bool, они не преобразуются неявно в числовые типы.

Организация такого ограничения для пользовательского типа, однако, не совсем проста. operator bool преобразование будет вызвано для преобразования в int, если это присутствует. Одно из решений C ++ 11 для ограничения ограничений — сделать оператор преобразования шаблоном, ограниченным std::enable_if, следующее:

#include <type_traits>  // std::enable_if, std::is_same

struct S
{
template< class Type >
operator Type* () const { return 0; }

template<
class Bool_type,
class Enabled = typename std::enable_if<
std::is_same<Bool_type, bool>::value, void
>::type
>
operator Bool_type () const { return false; }
};

auto main() -> int
{
bool const              b   = S();      // OK.
double const*  const    p   = S();      // OK.
int const               i   = S();      // !Doesn't compile.
}
40

Другие решения

C ++ 11 §4.12 Булевы преобразования

Значение арифметики, перечисление с незаданной областью, указатель или указатель на тип элемента может быть преобразовано в значение типа bool, Нулевое значение, значение нулевого указателя, или значение указателя нулевого члена преобразуется в false; любое другое значение преобразуется в true, Prvalue типа std::nullptr_t может быть преобразовано в тип значения bool; результирующее значение false,

Это правда, что nullptr является ключевым словом, но это литерал нулевого указателя, а не та же роль, что и bool, Подумайте о логических литералах, true а также false также ключевые слова.

19

В http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#654 , Джейсон Меррил утверждает

Все, что мы можем сделать с произвольным указателем, мы должны иметь возможность делать и с nullptr_t.

Я думаю, что следующий (немного искусственный) пример поддерживает этот аргумент (хотя я не совсем уверен, был ли он предназначен для этого случая)

template<typename T, typename P>
void safeProcess(T pointer, P &processor) {
bool isNonNull(pointer);
if(isNonNull) {
processor.process(pointer);
}
}

Который позволил бы проходить nullptr наряду с другими типами указателей, совместимыми с любым processor.process принимает.

5

C ++ 11 исправляет это, вводя новое ключевое слово, служащее отличительной константой нулевого указателя: nullptr. Он имеет тип nullptr_t, который неявно конвертируем и сопоставим с любым типом указателя или указателем на член. Он не является неявно конвертируемым или сопоставимым с целочисленными типами, за исключением bool. Хотя в первоначальном предложении указывалось, что значение типа nullptr не должно быть преобразовано в bool, рабочая группа по базовому языку решила, что такое преобразование было бы желательным для обеспечения согласованности с обычными типами указателей. Предложенные изменения формулировки были единогласно одобрены Рабочим документом в июне 2008 года. [2]

По причинам обратной совместимости 0 остается допустимой константой нулевого указателя.

char *pc = nullptr;     // OK
int  *pi = nullptr;     // OK
bool   b = nullptr;     // OK. b is false.
int    i = nullptr;     // error
0
По вопросам рекламы [email protected]