定义遍历函数的const和非const版本

defining const and non-const version of traversal function

本文关键字:const 和非 版本 遍历 函数 定义      更新时间:2023-10-16

我有一个类似于列表的数据结构:

template<typename T>
struct node {
  T val;
  unique_ptr<node<T>> next;
};

和一个简单遍历函数:

template<typename T, typename UnaryOp>
void traverse(node<T>& list, UnaryOp op) {
  node<T>* current = &list;
  while(current) {
    op(*current);
    current = current->next.get();
}

我现在需要一个 constnon-const 版本的traverse函数,根据上下文接受const node<T>& listnode<T>& list,最好避免代码重复。这是如何实现的呢?

一个可能的解决方案是创建一个静态模板函数,将*this作为转发引用:

class node
{
private:
    template <typename TSelf>
    static void traverse_impl(TSelf& self, node<T>& list, UnaryOp op)
    {
        node<T>* current = &list;
        while(current)
        {
            op(*current);
            current = current->next.get();
        }
    }
public:
    void traverse(node<T>& list, UnaryOp op)
    {
        traverse_impl(*this, list, op);
    }
    void traverse(node<T>& list, UnaryOp op) const
    {
        traverse_impl(*this, list, op);
    }
};

这是因为模板参数演绎规则——简而言之,TSelf将接受const和非const引用。

如果需要访问traverse_impl中的this成员,则使用self.member

此外,您可以使用std::conditionaltraverse_impl中的类似工具来执行不同的操作,具体取决于TSelfconst -ness。您还可以使用转发引用(TSelf&&),并处理由于引用限定符和完美转发而移动this的情况。