c++ - 通过 T * 匹配 nullptr

标签 c++ pointers c++11 metaprogramming generic-programming

使用 boost::variant指向 AST 节点的指针,其中可以包含特殊类型的值 std::nullptr_t ,表示空虚,我遇到了问题:形式为 [] (auto /* const */ * p) { /* use p */; } 的一般访问者或以下形式:

struct V
{
    template< typename T >
    void operator () (T /* const */ * p)
    { /* use p */; }
};

无法处理 std::nullptr_t 的值类型。

有很多可以想象的解决方法,但问题出现了:是否有很好的解释为什么没有(很可能受到高度限制)decltype(*nullptr)输入语言(*nullptr 格式错误,std::remove_pointer_t< std::nullptr_t >libc++ 中是 std::nullptr_t)?这有理论上的原因吗?

最佳答案

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?

我觉得要回答这个问题,必须看N1601由 Herb Sutter 和 Bjarne Stroustrup 提出。

有几个部分对我来说特别突出

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

因此,如果传递 nullptrnullptr_t 的结果是给定指针类型的空指针,那么取消引用它是有意义的(例如,通过 decltype(*nullptr) 将与取消引用任何其他类型的空指针相同。(在 delctype(*nullptr) 的特定情况下,我相信它类似于取消引用 null 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,通常被解释为整数类型,因此没有强制重载决议以选择指针重载的简单方法。现在我们有了 nullptr,我们可以区分指针和非指针类型,从而完全避免了这个问题。

关于c++ - 通过 T * 匹配 nullptr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35153996/

相关文章:

c++ - 如何遍历节点 vector

c++ - 这会正确释放数据吗?

c++理解在清理后访问全局变量不会给出某种错误

c++ - C++中使用双指针的动态二维数组

C++11 std::conditional 在运行时?

c++ - MinGW GCC 4.9.1 和浮点确定性

c++ - 指针不匹配和问题

c++ - 结构的 char* 成员被 strcmp 覆盖?

c++ - Schwarz 计数器和可变参数模板

c++ - 函数指针 : is the simple canonical use bad from a performance point of view? 如果是的话,c++11-ish 的替代方案是什么?