确定模板中模板参数的类型
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 T
在 operator*()
中没有意义,因为此 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' 有什么区别?
我正在尝试用 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 T
在 operator*()
中没有意义,因为此 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' 有什么区别?