Я не понимаю, почему следующий код компилирует ?
int main()
{
//int a = nullptr; // Doesn't Compile
//char b = nullptr; // Doesn't Compile
bool c = nullptr; // Compiles
return 0;
}
в то время как прокомментированный раздел не.
Я уже прошел этот а также этот.
И то и другое bool
а также nullptr
являются ключевыми словами, так что же уникального в других типах данных?
По той же причине, что и
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.
}
C ++ 11 §4.12 Булевы преобразования
Значение арифметики, перечисление с незаданной областью, указатель или указатель на тип элемента может быть преобразовано в значение типа
bool
, Нулевое значение, значение нулевого указателя, или значение указателя нулевого члена преобразуется вfalse
; любое другое значение преобразуется вtrue
, Prvalue типаstd::nullptr_t
может быть преобразовано в тип значенияbool
; результирующее значениеfalse
,
Это правда, что nullptr
является ключевым словом, но это литерал нулевого указателя, а не та же роль, что и bool
, Подумайте о логических литералах, true
а также false
также ключевые слова.
В 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
принимает.
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