确定模板中模板参数的类型

nic*_*225 1 c++ templates iterator typename

我正在尝试用 C++ 实现一个通用链表和链表迭代器。我有一个节点结构如下

template <typename T>
struct Node
{
    T m_data;
    Node<T>* m_next;
};
Run Code Online (Sandbox Code Playgroud)

我还有一个链表迭代器,它是一个模板,因此它可以生成常规和const 迭代器。

template <typename NodeType>
class LinkedListIterator
{  
private:
    NodeType* m_node;
public:
    LinkedListIterator(NodeType* n);
    T& operator*() const;
};
Run Code Online (Sandbox Code Playgroud)

我的问题是如何正确声明operator*()函数?我的期望是像下面这样的东西应该工作

LinkedListIterator<const Node<T>> my_iter(some_node_pointer);
*my_iter = new_value; // should not work
Run Code Online (Sandbox Code Playgroud)

据我所知,在返回Toperator*()没有意义,因为这个类没有访问的类型名称Node类。

我通过为Node类中的类型创建别名找到了一种解决方法,如下所示

template <typename T>
struct Node
{
    typedef T type_value;
    // rest of Node class...
};
Run Code Online (Sandbox Code Playgroud)

现在我可以在我的迭代器类中执行以下操作

template <typename NodeType>
class LinkedListIterator
{
public:
    typename NodeType::type_value& operator*() const;
};
Run Code Online (Sandbox Code Playgroud)

这似乎有效,并将返回正确的值。所以我的问题真的应该是,这是实现这一点的最佳方式吗?我是否需要typedef创建别名才能使用该类型?或者有没有办法确定类内的LinkedListIterator类型?

Jan*_*tke 5

typedef像这样使用 a是规范的方法,并且经常在标准库中完成。事实上,所有LegacyIterators应该定义value_typedifference_typereferencepointer,和iterator_category。只有这样,才能使用std::iterator_traits.

例如:

// a simple forward iterator
struct Iterator {
    using value_type = int;
    using reference = value_type &;
    using pointer = value_type *;
    using difference_type = std::ptrdiff_t;
    using iterator_category = std::forward_iterator_tag;

    // LegacyIterators also need two operators to be defined:

    // the result of operator* is unspecified, we can choose it freely
    value_type operator*();
    // operator++ needs to return a reference to self
    Iterator& operator++();
};

// we can now access the traits universally, as can various standard library functions
static_assert (std::is_same_v<std::iterator_traits<Iterator>::value_type, int> );
Run Code Online (Sandbox Code Playgroud)

总之,您正在做的是正确的方法,但您应该坚持使用这些确切的名称,以便标准库可以访问迭代器的特征。我也建议使用using而不是typedef. 它不仅可以=作为视觉分隔符,而且具有普遍适用性,例如,它可以像typedef. 请参阅C++11 中“typedef”和“using”的区别是什么?