通过 T * 匹配 nullptr
matching nullptr by T *
使用 boost::variant
指向 AST 节点的指针,它可以包含特殊类型 std::nullptr_t
的值,表示空,我遇到了问题:[] (auto /* const */ * p) { /* use p */; }
或 [] (auto /* const */ * p) { /* use p */; }
形式的通用访问者表格:
struct V
{
template< typename T >
void operator () (T /* const */ * p)
{ /* use p */; }
};
无法处理 std::nullptr_t
类型的值。
有很多可以想象的解决方法,但问题出现了:是否有很好的解释为什么没有(很可能受到高度限制)decltype(*nullptr)
类型的语言(*nullptr
是病态的-formed 并且 std::remove_pointer_t< std::nullptr_t >
是 std::nullptr_t
in libc++)?这有理论上的原因吗?
is there good explanation why there no (very likely highly restricted) decltype(*nullptr) type in the language (*nullptr is ill-formed and std::remove_pointer_t< std::nullptr_t > is std::nullptr_t in libc++)? Are there theoretical reasons for this?
我想要回答这个问题,我们必须看看 Herb Sutter 和 Bjarne Stroustrup 提出的N1601。
有几个部分让我印象深刻,尤其是
4.10 [conv.ptr]
A null pointer constant or an object of type nullptr_t can be converted to a
pointer type; the result is the null pointer value of that type
和 4.11 [conv.mem]:
A null pointer constant (4.10) or an object of type nullptr_t (4.10) can be converted to a pointer
to member type; the result is the null member pointer value of that type
因此,如果传递 nullptr
或 nullptr_t
的结果是给定指针类型的空指针,那么取消引用它是有意义的(例如,通过 decltype(*nullptr)
会与取消引用任何其他类型的空指针相同。(在 delctype(*nullptr)
的特定情况下,我认为它类似于取消引用空 void*
)。也就是说,你不应该这样做。
std::remove_pointer_t< std::nullptr_t > is std::nullptr_t
这是真的原因很简单,但原因却很难理解。
原因:
std::nullptr_t is the type of the null pointer literal, nullptr. It is a distinct type that is not itself a pointer type or a pointer to member type.
鉴于此,std::remove_pointer_t
没有效果是有道理的,因为 nullptr_t
不是指针类型。
原因
在 N1601 中,Sutter 和 Stroustrup 说
nullptr_t is not a reserved word. It is a typedef (as its _t typedef indicates) for decltype(nullptr) defined in <cstddef>. We do not expect to see much direct use of nullptr_t in real programs.
的确,这似乎是实际发生的事情。例如,Clang 3.9.0 在 stddef.h 中有以下内容:
namespace std { typedef decltype(nullptr) nullptr_t; }
using ::std::nullptr_t;
(而且他们说的不多 nullptr_t
出现在很多节目中也是对的)。
这仍然不能解释为什么它是这样定义的。要做到这一点,我认为我们需要回到更远一点的时间 N1488,同样是 Sutter 和 Stroustrup,他们说:
This use of the value 0
to mean different things (a pointer constant and an int
) in C++ has caused
problems since at least 1985 in teaching, learning, and using C++. In particular:
Distinguishing between null and zero. The null pointer and an integer 0
cannot be distinguished
well for overload resolution. For example, given two overloaded functions f(int)
and f(char*)
,
the call f(0)
unambiguously resolves to f(int)
. There is no way to write a call to f(char*)
with a
null pointer value without writing an explicit cast (i.e., f((char*)0)
) or using a named variable.
Note that this implies that today’s null pointer, 0
, has no utterable type.
Naming null. Further, programmers have often requested that the null pointer constant have a
name (rather than just 0
). This is one reason why the macro NULL
exists, although that macro is
insufficient. (If the null pointer constant had a type-safe name, this would also solve the
previous problem as it could be distinguished from the integer 0
for overload resolution and
some error detection.)
我认为这很好地解释了原因;程序员需要一种方法来区分 in 重载的指针和整数值,并且由于 NULL
通常被定义为 0
,通常被解释为整数类型,因此没有简单的方法来强制重载解析到 select 指针过载。现在我们有了 nullptr
,我们可以区分指针和非指针类型,从而完全避免了这个问题。
使用 boost::variant
指向 AST 节点的指针,它可以包含特殊类型 std::nullptr_t
的值,表示空,我遇到了问题:[] (auto /* const */ * p) { /* use p */; }
或 [] (auto /* const */ * p) { /* use p */; }
形式的通用访问者表格:
struct V
{
template< typename T >
void operator () (T /* const */ * p)
{ /* use p */; }
};
无法处理 std::nullptr_t
类型的值。
有很多可以想象的解决方法,但问题出现了:是否有很好的解释为什么没有(很可能受到高度限制)decltype(*nullptr)
类型的语言(*nullptr
是病态的-formed 并且 std::remove_pointer_t< std::nullptr_t >
是 std::nullptr_t
in libc++)?这有理论上的原因吗?
is there good explanation why there no (very likely highly restricted) decltype(*nullptr) type in the language (*nullptr is ill-formed and std::remove_pointer_t< std::nullptr_t > is std::nullptr_t in libc++)? Are there theoretical reasons for this?
我想要回答这个问题,我们必须看看 Herb Sutter 和 Bjarne Stroustrup 提出的N1601。
有几个部分让我印象深刻,尤其是
4.10 [conv.ptr]
A null pointer constant or an object of type nullptr_t can be converted to a pointer type; the result is the null pointer value of that type
和 4.11 [conv.mem]:
A null pointer constant (4.10) or an object of type nullptr_t (4.10) can be converted to a pointer to member type; the result is the null member pointer value of that type
因此,如果传递 nullptr
或 nullptr_t
的结果是给定指针类型的空指针,那么取消引用它是有意义的(例如,通过 decltype(*nullptr)
会与取消引用任何其他类型的空指针相同。(在 delctype(*nullptr)
的特定情况下,我认为它类似于取消引用空 void*
)。也就是说,你不应该这样做。
std::remove_pointer_t< std::nullptr_t > is std::nullptr_t
这是真的原因很简单,但原因却很难理解。
原因:
std::nullptr_t is the type of the null pointer literal, nullptr. It is a distinct type that is not itself a pointer type or a pointer to member type.
鉴于此,std::remove_pointer_t
没有效果是有道理的,因为 nullptr_t
不是指针类型。
原因
在 N1601 中,Sutter 和 Stroustrup 说
nullptr_t is not a reserved word. It is a typedef (as its _t typedef indicates) for decltype(nullptr) defined in <cstddef>. We do not expect to see much direct use of nullptr_t in real programs.
的确,这似乎是实际发生的事情。例如,Clang 3.9.0 在 stddef.h 中有以下内容:
namespace std { typedef decltype(nullptr) nullptr_t; }
using ::std::nullptr_t;
(而且他们说的不多 nullptr_t
出现在很多节目中也是对的)。
这仍然不能解释为什么它是这样定义的。要做到这一点,我认为我们需要回到更远一点的时间 N1488,同样是 Sutter 和 Stroustrup,他们说:
This use of the value
0
to mean different things (a pointer constant and anint
) in C++ has caused problems since at least 1985 in teaching, learning, and using C++. In particular:
Distinguishing between null and zero. The null pointer and an integer
0
cannot be distinguished well for overload resolution. For example, given two overloaded functionsf(int)
andf(char*)
, the callf(0)
unambiguously resolves tof(int)
. There is no way to write a call tof(char*)
with a null pointer value without writing an explicit cast (i.e.,f((char*)0)
) or using a named variable. Note that this implies that today’s null pointer,0
, has no utterable type.Naming null. Further, programmers have often requested that the null pointer constant have a name (rather than just
0
). This is one reason why the macroNULL
exists, although that macro is insufficient. (If the null pointer constant had a type-safe name, this would also solve the previous problem as it could be distinguished from the integer0
for overload resolution and some error detection.)
我认为这很好地解释了原因;程序员需要一种方法来区分 in 重载的指针和整数值,并且由于 NULL
通常被定义为 0
,通常被解释为整数类型,因此没有简单的方法来强制重载解析到 select 指针过载。现在我们有了 nullptr
,我们可以区分指针和非指针类型,从而完全避免了这个问题。