首页 > 解决方案 > 将代码从非模板转换为模板时,类不是模板错误

问题描述

我从内联行中收到一个错误,它说“DListCursor 不是模板”(它在它自己的 .hpp 文件中),并且“模板参数列表必须与参数列表匹配”,我不明白它是如何不这样做的。

DListNode.hpp

template <typename ItemType>

class DListNode {
    template <typename> friend class DListCursor;

public:
    DListNode(ItemType item, std::shared_ptr<DListNode> prev = nullptr, std::shared_ptr<DListNode> next = nullptr);

#ifdef DEBUG
    // ~DListNode() { std::cerr << "DListNode " << _item << std::endl; }
#endif

private:
    ItemType _item;
    std::shared_ptr<DListNode> _next;
    std::weak_ptr<DListNode> _prev;
};

template <typename ItemType>
inline DListNode<DListCursor<ItemType>>::DListNode(ItemType item, std::shared_ptr<DListNode<ItemType>> prev, std::shared_ptr<DListNode<ItemType>> next) {
    _item = item;
    _prev = prev;
    _next = next;
}

DListCursor.hpp - 我删除了 95% 的公共函数,因为我认为它们不相关。

template <typename ItemType>
class DListCursor {

public:
    // constructor
    DListCursor();

private:
    void _copy(const DListCursor &source);
    std::shared_ptr<DListNode> _find(size_t position) const;
    std::shared_ptr<DListNode> _head, _cursor, _tail;
};

标签: c++templates

解决方案


前向声明类与前向声明模板类有点不同。

当您键入:

class ClassA;

甚至:

struct ClassB;

这告诉编译器一个类型存在并将被实现。

请注意,一旦您这样做,您就可以使用以下类型:

void stuff(ClassA& parameter_of_declared_class);

并且编译器期望一个看起来像这样的定义:

class ClassA { /* ... */ };

如果ClassA实际上是模板,则函数声明语法将无效,因为它缺少模板参数。任何使用不完整类型的语法都将追溯无效。那真的很糟糕。

这就是为什么编译器必须提前知道您打算声明模板类型还是简单类型的原因。它们是不同类型的实体,应该以不同的方式声明。

一个模板类被转发声明如下:

template<typename> class ClassA;

请注意,它看起来很像您的朋友声明。

如果您有默认模板参数,它们也必须在声明中:

template<typename, typename = int> class ClassA;

推荐阅读