【问题标题】:Why std::distance doesnt work on mix of const and nonconst iterators? [duplicate]为什么 std::distance 不适用于 const 和非 const 迭代器的混合? [复制]
【发布时间】:2012-03-26 04:59:14
【问题描述】:

就像问题所说的那样,我想知道其中的原因。因为当我尝试获取const 和非const 迭代器之间的距离时出现错误。

vector<int> v;
auto it=v.begin();
auto cit=v.cbegin();
distance(it,cit);


no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<int*, std::vector<int> >&, __gnu_cxx::__normal_iterator<const int*, std::vector<int> >&)

根据我对迭代器的有限理解,我认为它没有理由不工作。

【问题讨论】:

    标签: c++ c++11 iterator


    【解决方案1】:

    在对std::distance 的调用中有一个可变迭代器和一个常量迭代器,因此模板参数推导失败。您可以通过显式指定模板参数来解决此问题。

    std::vector<int> v;
    auto i1 = v.begin();
    auto i2 = v.cbegin();
    
    auto dist = std::distance<std::vector<int>::const_iterator>( i1, i2 );
    

    【讨论】:

      【解决方案2】:

      那是因为std::distance() 只接受一个模板参数:

      template <class InputIterator>
      iterator_traits<InputIterator>::difference_type
      distance(InputIterator first, InputIterator last);
      

      因此,firstlast 必须可以转换为相同的类型,并且模板解析很遗憾不会考虑vector&lt;int&gt;::iterator 可以转换为vector&lt;int&gt;::const_iterator

      【讨论】:

      • 嗯,他们为什么不只创建带有 2 个模板参数的模板?是否可以在 cpp core lang 中做到这一点?我要问的是设计决策还是语言限制?
      • 要清楚,我知道他们可以使用 2 个模板参数制作模板,但我想知道它会与 1 个模板参数版本冲突
      • @NoSenseEtAl,我会说设计决策。这种方式更简单,并且计算不同类型的迭代器(例如,随机访问迭代器和前向迭代器)之间的距离可能不是您想要经常做的事情。你确实可以编写一个带有两个模板参数的版本,但是这样可以解决什么现实问题呢?
      • @NoSenseEtAl:不会冲突,也没有理由不能定义自己的双参数版本(尽管显然不在std 中)。这只是该标准的许多小细节之一,并没有达到应有的水平。也许下一个版本会修复它。
      • firstlast 必须具有相同的类型”,或者可以转换为相同的类型。方便的是,该标准要求 vector::iterator 可转换为 vector::const_iterator
      【解决方案3】:

      正如大家所说,这是因为std::distance 只接受一种迭代器类型,并且模板参数推导无法选择它应该是哪一种(即使考虑到iterator 转换为@987654323,其中只有一种是可能的@ 但不返回)。

      可能值得编写这样的模板:

      template <typename Container>
      typename Container::const_iterator constify(const Container &, typename Container::iterator it) {
          return it;
      }
      

      那么你可以像这样强制模板推导:

      std::distance(constify(v, it), cit);
      

      而不是写出那个很棒的长类型。 Container&amp; 参数很可惜,因为 AFAIK Container 不能仅从迭代器参数推导出来。

      【讨论】:

        【解决方案4】:

        std::distance 将与这两个迭代器一起使用,不起作用的是模板参数推断。编译器正在尝试解析要替换第一个模板参数的类型,并且有两个潜在的候选者,根据标准,它们最终会失败。

        你可以做两件事之一,要么只比较相同类型的迭代器,要么将类型提供给模板:

        std::distance<std::vector<int>::const_iterator>( v.begin(), v.cbegin() );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-10
          • 1970-01-01
          • 2011-05-03
          • 2011-01-10
          • 1970-01-01
          相关资源
          最近更新 更多