Мне любопытно узнать, как работает nullptr
. Стандарты N4659 и N4849 говорят:
- он должен иметь тип
std::nullptr_t
; - вы не можете взять его адрес;
- его можно напрямую преобразовать в указатель и указатель на элемент;
sizeof(std::nullptr_t) == sizeof(void*)
;- его преобразование в
bool
равноfalse
; - его значение может быть преобразовано в целочисленный тип аналогично
(void*)0
, но не наоборот;
Так что в основном это константа с тем же значением, что и (void*)0
, но другого типа. Я нашел реализацию std::nullptr_t
на своем устройстве, и она выглядит следующим образом.
#ifdef _LIBCPP_HAS_NO_NULLPTR
_LIBCPP_BEGIN_NAMESPACE_STD
struct _LIBCPP_TEMPLATE_VIS nullptr_t
{
void* __lx;
struct __nat {int __for_bool_;};
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t() : __lx(0) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t(int __nat::*) : __lx(0) {}
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR operator int __nat::*() const {return 0;}
template <class _Tp>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
operator _Tp* () const {return 0;}
template <class _Tp, class _Up>
_LIBCPP_INLINE_VISIBILITY
operator _Tp _Up::* () const {return 0;}
friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator==(nullptr_t, nullptr_t) {return true;}
friend _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR bool operator!=(nullptr_t, nullptr_t) {return false;}
};
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR nullptr_t __get_nullptr_t() {return nullptr_t(0);}
#define nullptr _VSTD::__get_nullptr_t()
_LIBCPP_END_NAMESPACE_STD
#else // _LIBCPP_HAS_NO_NULLPTR
namespace std
{
typedef decltype(nullptr) nullptr_t;
}
#endif // _LIBCPP_HAS_NO_NULLPTR
Хотя меня больше интересует первая часть. Кажется, он удовлетворяет пунктам 1-5, но я понятия не имею, почему у него есть подкласс __nat и все, что с ним связано. Я также хотел бы знать, почему он терпит неудачу при интегральных преобразованиях.
struct nullptr_t2{
void* __lx;
struct __nat {int __for_bool_;};
constexpr nullptr_t2() : __lx(0) {}
constexpr nullptr_t2(int __nat::*) : __lx(0) {}
constexpr operator int __nat::*() const {return 0;}
template <class _Tp>
constexpr
operator _Tp* () const {return 0;}
template <class _Tp, class _Up>
operator _Tp _Up::* () const {return 0;}
friend constexpr bool operator==(nullptr_t2, nullptr_t2) {return true;}
friend constexpr bool operator!=(nullptr_t2, nullptr_t2) {return false;}
};
inline constexpr nullptr_t2 __get_nullptr_t2() {return nullptr_t2(0);}
#define nullptr2 __get_nullptr_t2()
int main(){
long l = reinterpret_cast<long>(nullptr);
long l2 = reinterpret_cast<long>(nullptr2); // error: invalid type conversion
bool b = nullptr; // warning: implicit conversion
// edditor error: a value of type "std::nullptr_t" cannot be used to initialize an entity of type "bool"
bool b2 = nullptr2;
if (nullptr){}; // warning: implicit conversion
if (nullptr2){};
};
nullptr_t
является фундаментальным типом. Как реализованint
? - person L. F.   schedule 18.04.2020#ifdef _LIBCPP_HAS_NO_NULLPTR
. Это похоже на лучший обходной путь, когда компилятор не предоставляетnullptr
. - person chris   schedule 18.04.2020float
- person Ardent Coder   schedule 18.04.2020nullptr_t
является фундаментальным типом. Реализация его как типа класса не дает соответствующей реализации. Смотрите комментарий Криса. - person L. F.   schedule 18.04.2020__nat
и почему он здесь, может быть, это поможет мне в моем собственном коде. - person Fullfungo   schedule 18.04.2020operator bool
позволит преобразовать его, скажем, вint
или типы классов, конструируемые изbool
. - person L. F.   schedule 18.04.2020is_class
иis_null_pointer
не могут быть верны для одного и того же типа. Только одна из функций категории основного типа может возвращать значение true для определенного тип. - person Nicol Bolas   schedule 18.04.2020is_class
иis_null_pointer
может лгать, создавая явное исключение для этого типаstd::nullptr_t
, возвращая неверные значения. - person Nicol Bolas   schedule 18.04.2020nullptr
очень похоже на ключевые словаtrue
иfalse
: все они являются литералами, представляющими значения для типа, у которого изначально очень мало значений. Есть только два значенияbool
и только одно значениеstd::nullptr_t
. - person aschepler   schedule 18.04.2020