如何改进自引用模板的实现
How to improve the self-referencing template implementation?
如何在给定的自引用模板实现中去掉抽象类?
我只是尝试实现一个跳过列表数据结构。所以我想创建模板Node,这样我就可以为不同的节点类实例化下一个链接的类,以避免类强制转换。发现了这些问题:
模板参数中的自引用模板
如何正确声明自引用模板类型?
但他们都没有解决方案。然后,我基于两条继承线制定了自己的解决方案。一个是"抽象"模板的序列(用于下一个参数的传播)。另一个是实例化具体的类。但感觉在没有多余抽象模板(NodeAbstract、NodeWithKeyAbstract等)的情况下处理同样的问题是可以改进的。经过几次自己的尝试,我想请你帮助我:
template <class Value, class Next >
class NodeAbstract
{
public:
Value m_value;
Next * next;
NodeAbstract () : next(0) {}
Next * getNext() {return next;}
};
template <class Value, class Key, class Next >
class NodeWithKeyAbstract : public NodeAbstract <Value, Next >
{
public:
Key m_key;
};
template <class Value, class Key>
class NodeWithKey : public NodeWithKeyAbstract <Value, Key, NodeWithKey<Value,Key> >
{
};
template <class Value, class Key, int maxlevel, class Next>
class NodeSkipListAbstract : public NodeWithKeyAbstract<Value, Key, Next >
{
public:
Next * nextjump[maxlevel-1];
};
template <class Value, class Key, int maxlevel>
class NodeSkipList : public NodeSkipListAbstract<Value, Key, maxlevel, NodeSkipList<Value, Key, maxlevel> >
{
};
如果我理解正确的话,你的问题基本上是中不同的maxlevel
值会产生不同的类,所以你不能使用一个数组来存储所有的类(如果我错了,请纠正我)。
你不能完全摆脱抽象类——如果你想把具有不同最大级别的节点作为不同的类(不同的模板专业化),你必须为它们提供一些共同点。
好消息是,你可以去掉Curioly Recurring Template Pattern——因为你使用指针,所以如果你是抽象的,你不必引用确切的实现类型(例如,知道确切的模板专业化),你可以访问你需要的所有信息。您的代码也可以简化一点。
考虑这个代码:
template <class Key, class Value>
class Node {
public:
virtual ~Node() = default;
virtual std::size_t MaxLevel() const = 0;
virtual Node* Skip(size_t level) const = 0;
// add setter as well
Key key;
Value value;
};
template <class Key, class Value, std::size_t max_level>
class NodeImpl : public Node<Key, Value> {
public:
typedef Node<Key, Value> node_type;
NodeImpl() : skips() {}
size_t MaxLevel() const { return max_level; }
node_type* Skip(std::size_t level) const {
return level < max_level ? skips[level] : nullptr;
}
// add setter as well
private:
node_type* skips[max_level];
};
template <class Key, class Value>
class SkipList {
public:
typedef Node<Key, Value> node_type;
node_type* head;
};
这里Node
为您提供了一个"跳过"行为的抽象。NodeImpl
将用于生成具有不同最大级别的Node
,但最终使用的实现对您来说是透明的——您将只使用Node
的接口。此外,在语法级别上,您将只使用Node*
类型,所以各种实现都不会成为问题。虚拟析构函数将确保delete
释放所有内存,并且key
和value
始终可以作为公共字段访问。
这个代码当然可以改进。原始数组可以用std::array
替换。如果您决定使用在构造函数中设置大小的std::vector
而不是数组(那么您将只有Node
和SkipList
),那么max_level
作为模板的整个想法就可以摆脱了。作为奖励,创建新节点会更容易,因为现在你必须编写一些工厂,专门化所有NodeImpl
的值,从1到某个值。另外,指针可以用一些智能指针代替,以避免内存泄漏。
- 如果没有malloc,链表实现将失败
- 如何在c++中实现处理器调度模拟器
- 如何在c++中使用引用实现类似python的行为
- 实现无开销push_back的最佳方法是什么
- 使用简单类型列表实现的指数编译时间.为什么
- 函数何时会在c++中包含stack_Unwind_Resume调用
- 如何在BST的这个简单递归实现中消除警告
- 实现一个在集合上迭代的模板函数
- 我应该实现右值推送功能吗?我应该使用std::move吗
- Python中的for循环与C++有何不同
- 如何正确实现和访问运算符的各种自定义枚举器
- C++Union/Struct位域的实现和可移植性
- 这个极客对极客的trie实现是否存在内存泄漏问题
- 在c++中实现LinkedList时,应出现未处理的错误
- 为什么不能修改对象中的值?另外,我如何改进此链表?
- 为左值和右值的包装器实现C++范围
- 改进了 C++ 中计时器(超时事件)的实现
- 如何改进自引用模板的实现
- 我的 PRNG 实现与我尝试复制的实现有何不同?
- 有关改进分配器算法实现的建议