你记得在算法中的本科讲座中,有一个概念是非常方便的Nil,可以分配或比较任何东西.(顺便说一下,我从未在计算机科学专业读过本科生.)在Python中我们可以使用None; 在Scala中有Nothing(如果我正确地理解它,它是所有东西的子对象).但我的问题是,我们如何才能拥有NilC++?以下是我的想法.
我们可以使用Singleton设计模式定义单个对象,但我目前的印象是,大多数人都会在想到这一点时畏缩.
或者我们可以定义全局或静态.
我的问题是,在这两种情况中,我都想不出能够将任何类型的任何变量分配给Nil或能够比较任何类型的任何对象的方法Nil.Python None是有用的,因为Python是动态类型的; Scala Nothing(不要与Scala混淆Nil,这意味着空列表)优雅地解决了这个问题,因为它Nothing是一切的子对象.那么Nil在C++中有一种优雅的方式吗?
Rei*_*ica 10
不,nilC++中没有通用值这样的东西.逐字,C++类型是不相关的,不共享共同的值.
您可以使用继承来实现某种形式的可共享值,但必须明确地这样做,并且只能对用户定义的类型执行此操作.
Bar*_*rry 10
这是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并且使用起来更昂贵(虽然只是一点点,虽然这一点可能很重要).
我们可以将这些想法结合起来,实际上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)