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

Determine type of template parameter in template

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

template <typename T>
struct Node
{
    T m_data;
    Node<T>* m_next;
};

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

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

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

LinkedListIterator<const Node<T>> my_iter(some_node_pointer);
*my_iter = new_value; // should not work

我明白 returning Toperator*() 中没有意义,因为此 class 无法访问 [=19= 中的类型名称] class.

我通过为 Node class 中的类型创建一个别名找到了解决方法,就像这样

template <typename T>
struct Node
{
    typedef T type_value;
    // rest of Node class...
};

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

template <typename NodeType>
class LinkedListIterator
{
public:
    typename NodeType::type_value& operator*() const;
};

这似乎可行,并且 return 会得到正确的值。所以我的问题真的应该是,这是实现这个的最好方法吗?我是否需要 typedef 才能创建别名才能使用该类型?或者有没有办法确定 LinkedListIterator class 中的类型?

像这样使用 typedef 是规范的方法,并且在标准库中经常使用。事实上,所有 LegacyIterators should define value_type, difference_type, reference, pointer, and iterator_category. Only then can their traits be accessed universally using 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> );

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