C++中"Nil"的概念

Ray*_*Ray 7 c++ null

你记得在算法中的本科讲座中,有一个概念是非常方便的Nil,可以分配或比较任何东西.(顺便说一下,我从未在计算机科学专业读过本科生.)在Python中我们可以使用None; 在Scala中有Nothing(如果我正确地理解它,它是所有东西的子对象).但我的问题是,我们如何才能拥有NilC++?以下是我的想法.

我们可以使用Singleton设计模式定义单个对象,但我目前的印象是,大多数人都会在想到这一点时畏缩.

或者我们可以定义全局或静态.

我的问题是,在这两种情况中,我都想不出能够将任何类型的任何变量分配给Nil或能够比较任何类型的任何对象的方法Nil.Python None是有用的,因为Python是动态类型的; Scala Nothing(不要与Scala混淆Nil,这意味着空列表)优雅地解决了这个问题,因为它Nothing是一切的子对象.那么Nil在C++中有一种优雅的方式吗?

Rei*_*ica 10

不,nilC++中没有通用值这样的东西.逐字,C++类型是不相关的,不共享共同的值.

您可以使用继承来实现某种形式的可共享值,但必须明确地这样做,并且只能对用户定义的类型执行此操作.

  • @Ray是的,没有办法让普通的普通Nil.充其量,您可以使用适用于某些类型子集的Nil. (5认同)
  • 最接近该概念的是`nullptr`,但这是指针特有的 (2认同)

Bar*_*rry 10

您描述的有两个相关概念Nil:单元类型选项类型.

单位类型

这是NoneTypePython中的内容,nullptr_t并且在C++中,它只是一种特殊类型,具有传达此特定行为的单个值.由于Python是动态类型的,因此可以对任何对象进行比较,None但在C++中我们只能对指针进行比较:

void foo(T* obj) {
    if (obj == nullptr) {
        // Nil
    }
}
Run Code Online (Sandbox Code Playgroud)

这在语义上与python相同:

def foo(obj):
    if foo is None:
        # Nil
Run Code Online (Sandbox Code Playgroud)

选项类型

Python没有(或需要)这样的功能,但所有ML系列都有.这可以在C++中实现boost::optional.这是一种类型安全的封装,即特定对象可能具有值或不具有值.这个想法在功能家族中比在C++中更具表现力但是:

def foo(obj: Option[T]) = obj match {
    case None => // "Nil" case
    case Some(v) => // Actual value case
}
Run Code Online (Sandbox Code Playgroud)

虽然在C++中也很容易理解,但是一旦你看到它:

void foo(boost::optional<T> const& obj) {
    if (obj) {
        T const& value = *obj;
        // etc.
    }
    else {
        // Nil
    }
}
Run Code Online (Sandbox Code Playgroud)

这里的优点是选项类型是一个值类型,您可以轻松地表达任何"值"(例如,您optional<int*>可以存储nullptr为值,与"Nil"分开).此外,这可以适用于任何类型,而不仅仅是指针 - 只需要为增加的功能付费.一个optional<T>将比一个更大,T并且使用起来更昂贵(虽然只是一点点,虽然这一点可能很重要).

一个C++无

我们可以将这些想法结合起来,实际上Nil用C++编写,至少有一个用于指针和选项.

struct Nil_t { };
constexpr Nil_t Nil;

// for pointers
template <typename T>
bool operator==(const T* t, Nil_t ) { return t == nullptr; }

template <typename T>
bool operator==(Nil_t, const T* t ) { return t == nullptr; }

// for optionals, rhs omitted for brevity
template <typename T>
bool operator==(const boost::optional<T>& t, Nil_t ) { return !t; }
Run Code Online (Sandbox Code Playgroud)

(请注意,我们甚至可以将其概括为实现的任何内容 operator!

template <typename T>
bool operator==(const T& t, Nil_t ) { return !t; }
Run Code Online (Sandbox Code Playgroud)

,但最好将自己局限于明确的案例,我喜欢指针和选项给你的明确性

从而:

int* i = 0;
std::cout << (i == Nil); // true
i = new int(42);
std::cout << (i == Nil); // false
Run Code Online (Sandbox Code Playgroud)