【问题标题】:c++ custom iterator const conversion done rightc++ 自定义迭代器 const 转换正确完成
【发布时间】:2021-02-13 20:16:55
【问题描述】:

我尝试为自定义容器实现与 std 兼容的自定义迭代器的复制构造函数。 容器看起来像这样:

template <typename T, Alloc>
class container {
    template <typename ValueType>
    class raw_iterator;
    
    ...
    using value_type = T;
    ...

    using iterator = raw_iterator<value_type>
    using const_iterator = raw_iterator<const value_type>
    ...
}

raw_iterator 看起来像这样:

template <typename T, Alloc>
template <typename ValueType>
class container<T, Alloc>::raw_iterator {
    ...
}

如果我是对的,我必须为迭代器和 const_iterator 都实现一个复制构造函数,以便可以将迭代器复制到相同的类型,并且可以将普通迭代器复制到 const_iterator。
如何实现?

PS:我必须在复制构造函数中提供一些功能,所以我不能使用隐式生成的构造函数。

【问题讨论】:

  • 您可以为const_iterator 创建一个隐式构造函数,它以iterator 作为参数。然后一切都会“正常工作”。
  • 正如我所说,我需要在复制构造函数中添加一些逻辑,而不仅仅是自动生成的。除此之外,我将如何在其中一个模板特殊化上添加这样的构造函数?
  • 好,我举个例子。

标签: c++ iterator containers std


【解决方案1】:

您可以为 const_iterator 创建一个隐式构造函数,该构造函数将迭代器作为参数。然后一切都会“正常工作”。

这是我认为您想要的示例:

#include <type_traits>

template <typename ValueType>
class raw_iterator {
  public:
    // Typedefs
    using non_const_value_type = std::remove_const_t<ValueType>;
    using const_value_type = std::add_const_t<non_const_value_type>;

    // Constructor - Need extra template argument here to allow SFINAE to work.
    template <class U = ValueType,
      std::enable_if_t<std::is_same<U, const_value_type>::value, int> = 0>
    raw_iterator (raw_iterator<non_const_value_type> const & other) {
      // Do stuff.
    }

  private:
    // Friends - Make raw_iterator<X> friend of raw_iterator<X const>
    friend std::conditional_t<
        std::is_same<ValueType, non_const_value_type>::value,
        raw_iterator<const_value_type>, void
      >;
};

有一个条件构造函数采用 raw_iterator&lt;AnythingNonConst&gt;,仅当 raw_iterator 自己的寺庙类型为 AnythingConst 时才存在。

此外,raw_iterator&lt;AnythingNonConst&gt; 是raw_iterator&lt;AnythingConst&gt; 的朋友,但反之则不然。所以你可以在条件构造函数中复制你想要的任何成员。

这是一个在线示例:https://wandbox.org/permlink/8gDzHyheIrpsTL5y。

【讨论】:

  • perfekt,所以 std::enable_if 用于根据 ValueType 启用/禁用正确的构造函数?
  • 是的,它使用 SFINAE 来做到这一点。我无法在评论中充分解释这一点,但如果您想了解更多信息,这里是一个起点:en.wikipedia.org/wiki/Substitution_failure_is_not_an_error。还有大量关于它的博客文章。这是一个很好的技巧,经常派上用场!
  • 基本上,当U != const_value_type 时,std::enable_if_t 是 std::enable_if 类中实际上不存在的类型的 typedef。由于 SFINAE,这不是错误,而是编译器简单地忽略了该函数。在这种情况下,仅当 U == const_value_type 存在 typedef 时,编译器才会考虑该构造函数。
  • 这在 c++ std 中有效还是编译器实现的东西?我猜这是否是它在标准中有效的模式...
  • 适用于所有 C++ 编译器,这是一种非常“标准”的做事方式。我的示例代码适用于 C++14,但您也可以轻松地使其也适用于 C++11,只需在这里和那里添加一些 typenames。
猜你喜欢
  • 2015-08-23
  • 1970-01-01
  • 2016-04-05
  • 2020-04-21
  • 1970-01-01
  • 2015-11-19
  • 2012-03-16
  • 1970-01-01
  • 2011-03-24
相关资源
最近更新 更多