C语言中如何实现类似Optional的功能?
摘要:Optional 这是一个完整的 optional 类型实现,类似于 C++17 的 std::optional。 整体结构 template<class T>
Optional
这是一个完整的 optional 类型实现,类似于 C++17 的 std::optional。
整体结构
template<class T>
struct optional{
private:
T value;
bool has_value;
public:
optional(T value) : value(value),has_value(has_value){}
T value(){return value;}
bool has_value(){return has_value;}
};
上面是一个最简单的optional结构,可以满足基本的判断有无值,取出值等。
但是过于简单,很多都没有考虑到,比如,我们指定了类型T,那么构建otional的时候无论值是否存在,value都会被构造。有着不必要的构造和析构等等...
实现
union包装
既然无论有值与否都会构造析构,那么有没有可以没有值就不构造的方法呢?在C++中,union类型的对象默认不会自动构造和析构函数。因为union可能含有多个成员,而union自己是不知道当前成员是谁的,也就无从谈起自动构造和析构。
union{
T value;
};
这样使用union存储值,可以精确的控制构造和析构时机。
值构造
optional(T &&value) noexcept : _has_value(true) {
new (&_value) T(std::move(value));
}
optional(T const &value) noexcept : _has_value(true) {
new (&_value) T(value);
}
我们提供了两种从值构造的方式,分别是右值和左值构造。
重点在于value的构造,union默认开辟最大成员成员所占内存。因为我们这里的union只有一个value,那么所占内存就是T的字节大小。我们要做的就是从已经开辟好的内存直接构造T.使用placement new在union内存构造对象;
new (&value) T(value);
在value的内存上,以value(参数value)为值构造union成员value.
空状态构造
我们需要支持当不存在值时的构造。方法是可以先创建一个空状态的辅助类型。
struct nullopt_t {
explicit nullopt_t() = default;
};
inline constexpr nullopt_t nullopt;
我们这里创建了 nullopt_t 类型,同时添加了全局的 nullopt 对象。这样我们实现一个空构造的函数,只要传入代表空的辅助类型,就说明为 optional 空。
optional(nullopt_t) noexcept : _has_value(false) {}
optional() noexcept : optional(nullopt) {}
拷贝/移动
其他的拷贝/移动的构造或者赋值函数形式大差不差,一通百通。
