如果泛型类型 T 有合适的构造函数可供使用,如何知道它?

How to know a generic type T if it has an appropriate constructor for use?

我正在实现一个双向链表,它的头部和尾部都有哨兵节点,假设这个 class 名为 ListNodeList 中的私有结构。这个class有一个私有方法Init用于初始化头节点和尾节点,在List的构造函数中调用。

template<typename T>
class List {
public:
    List() {
        Init();
    }
    ...

private:
    struct Node {
        T data;
        Node* prev;
        Node* next;
        
        // Constructors
    };

    size_t size;
    Node* head;
    Node* tail;

    void Init() {
        // Codes arise some problem if instances of T have no default constructor.
        head = new Node;
        tail = new Node;
        head->prev = nullptr;
        head->next = tail;
        tail->prev = head;
        tail->next = nullptr;
        size = 0;
    }
};

现在的问题是,如果 T 的实例没有默认构造函数,我无法使用 head = new Node;tail = new Node; 创建哨兵节点。 new 运算符总是分配一块内存并构造它。在构造Node对象时,必须使用T的一些构造函数来初始化Node中的data字段。

有没有办法检查 T 的哪些构造函数(复制和移动构造函数除外)我可以用来构造 T 类型的变量 data?或者我可以只初始化 Node 中的 prevnext 字段,而不初始化 data 字段吗?

你的代码有一个类型 T,它应该遵循你需要的概念。

在你的情况下,你希望它是默认可构造的。如果模板的实例化器不提供符合的 T,它会得到一个大的模板错误。

您可以在您的代码中添加一个 static_assert,以提供更好的消息(如果您的方法未被直接使用,则可以更早地提供)

您可以使用:static_assert(is_default_constructible_v)。 存在更多变体,如果它不应该抛出...,请参阅 documentation

在 C++20 中,您也可以使用概念来限制 T。我对它们不甚了解,所以我会留给您寻找正确的语法。

还有其他解决方案,例如存储 std::optional,或在 init 函数上使用可变参数来构造 T。 在这种情况下,如果您不介意放置新闻,您可能希望使用 std::is_constructible. std::aligned_storage 限制代码也可以。一切都取决于你想用这个实现什么。