我很好奇如何使用 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
是如何实现的? - L. F.#ifdef _LIBCPP_HAS_NO_NULLPTR
。这似乎是一个最佳尝试的解决方法,当编译器不提供nullptr
时使用。 - chrisnullptr_t
是一种基本类型。将其实现为类类型不符合规范。请参考Chris的评论。 - L. F.is_class
和is_null_pointer
不能同时为真。对于特定类型,仅有一个基本类型类别函数可以返回true。 - Nicol Bolas