使用std::experimental::optional来实现列表

Use std::experimental::optional to implement a list

本文关键字:实现 列表 experimental std 使用 optional      更新时间:2023-10-16

我想知道是否可以使用std::experimental::optional实现单(也可能是双)链表。

template <typename T>
struct node {
    std::experimental::optional<node<T>> next;
    T data;
};

这种设计的优点/缺点是什么?新的c++1z功能可以用来实现哨兵吗?或者把它们一起去掉?这也会扩展到n元树吗?

以这种方式实现链表是不可能的,因为node-类型总是不完整的。下面是一个更完整的例子来说明这个问题:

#include <iostream>
#include <experimental/optional>
template <typename T>
struct node {
    std::experimental::optional<node<T>> next;
    T data;
};
int main( int, char ** )
{
    std::cout << sizeof( node<int> ) << std::endl;
    return 0;
}

关键是optional<T>要求T是完整的,但在定义next时,node是不完整的。optional<T>需要完整类型的原因是它将T直接存储在optional对象中,即它不在堆上分配内存。因此,它必须知道T的大小。在内部,它包含一个sizeof( T )缓冲区。在内存布局方面,你可以把optional<T>想象成

template <class T>
struct optional
{
    bool _containsValue;
    char _buffer[ sizeof( T ) ];
};

但在实践中,由于存储器对准的要求,它更为复杂。

在您的情况下,为了知道optional<node>的大小,它必须知道node的大小,为此,它必须了解optional<node>的大小。

这是不可能的,因为optional<T>要求T是完整的。

根据N3672(std::optional的建议书):

类模板optional对T的要求很小:它必须是一个左值引用类型,或者是一个满足Destrucable要求的完整对象类型。