自动它= vector.begin()结果类型不能转换为const_iterator [英] auto it = vector.begin() resulting type is not convertible to const_iterator

查看:137
本文介绍了自动它= vector.begin()结果类型不能转换为const_iterator的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

要求容器提供一个iterator类型,该类型可以隐式转换为const_iterator.鉴于此,我尝试使用auto通过vector::begin()初始化对象,并在RHS为const_iteratorstd::distance中使用该结果对象.这是行不通的.这是一个完整的示例:

Containers are required to provide an iterator type which is implicitly convertible to a const_iterator. Given this, I am trying to use auto to initialize an object via vector::begin(), and use that resulting object in std::distance where the RHS is a const_iterator. This isn't working. Here is a complete example:

#include <cstdlib>
#include <vector>
#include <iterator>
#include <iostream>

typedef std::vector <char> Packet;
typedef std::vector <Packet> Packets;

template <typename Iter> 
Iter next_upto (Iter begin, Iter end, size_t n)
{
    Iter ret = begin;
      for (; n > 0 && ret != end; ++ret, --n)
            ;   
        return ret;
}

Packets::const_iterator Process (Packets::const_iterator begin, Packets::const_iterator end)
{
  Packets::const_iterator ret = begin;
  while (ret != end)
    ++ret;  // do something
  return ret;
}

int main()
{
  Packets test (100); // vector of 100 default-initialized packets

  // process them 10 at a time
  for (auto it = test.begin();
    it != test.end();
    it = next_upto (it, test.end(), 10))
  {
     auto itr = Process (it, next_upto (it, test.end(), 10));
     Packets::const_iterator it2 = it; 
     const size_t n1 = std::distance (it2, itr);
     const size_t n = std::distance (it, itr);
     std::cout << "Processed " << n << " packets\n";
  }
}

在g ++ 4.8.1(和4.8.2)下编译时,得出:

Under g++ 4.8.1 (and 4.8.2) compiling this yields:

[1/2] Building CXX object CMakeFiles/hacks.dir/main.o
FAILED: /usr/bin/g++    -Wall -std=c++11 -g -MMD -MT CMakeFiles/hacks.dir/main.o -MF "CMakeFiles/hacks.dir/main.o.d" -o CMakeFiles/hacks.dir/main.o -c main.cpp
main.cpp: In function ‘int main()’:
main.cpp:39:45: error: no matching function for call to ‘distance(__gnu_cxx::__normal_iterator<std::vector<char>*, std::vector<std::vector<char> > >&, __gnu_cxx::__normal_iterator<const std::vector<char>*, std::vector<std::vector<char> > >&)’
      const size_t n = std::distance (it, itr);
                                             ^
main.cpp:39:45: note: candidate is:
In file included from /usr/include/c++/4.8/bits/stl_algobase.h:66:0,
                 from /usr/include/c++/4.8/vector:60,
                 from main.cpp:2:
/usr/include/c++/4.8/bits/stl_iterator_base_funcs.h:114:5: note: template<class _InputIterator> typename std::iterator_traits<_Iterator>::difference_type std::distance(_InputIterator, _InputIterator)
     distance(_InputIterator __first, _InputIterator __last)
     ^
/usr/include/c++/4.8/bits/stl_iterator_base_funcs.h:114:5: note:   template argument deduction/substitution failed:
main.cpp:39:45: note:   deduced conflicting types for parameter ‘_InputIterator’ (‘__gnu_cxx::__normal_iterator<std::vector<char>*, std::vector<std::vector<char> > >’ and ‘__gnu_cxx::__normal_iterator<const std::vector<char>*, std::vector<std::vector<char> > >’)
      const size_t n = std::distance (it, itr);
                                             ^

我知道我可以通过调用cbegin()cend()而不是begin()end()来修复此特定实例,但是由于begin()end()返回的类型应该可以转换为const_iterator,我不确定我为什么需要这样做.

I'm aware that I can fix this particular instance by calling cbegin() and cend() rather than begin() and end(), but since begin() and end() return a type that should be convertible to const_iterator, I'm not sure I understand why this is needed.

为什么在这种情况下auto会推导无法转换为const_iterator的类型?

Why does auto deduce a type in this case that is not convertible to const_iterator?

推荐答案

您的问题可以简化为以下示例,该示例由于相同的原因而失败.

Your problem can be reduced to the following example, which fails for the same reasons.

#include <vector>
#include <iterator>
int main()
{
    std::vector<int> v;
    std::vector<int>::const_iterator it1 = v.begin();
    auto it2 = v.end();
    auto n = std::distance(it1, it2);
}

std::distance 定义为两个参数使用相同的模板参数类型,并且模板参数推导失败,因为您有const_iteratoriterator.

从函数调用中推导模板参数时不考虑用户定义的转换,并且由于在这种情况下两个参数具有不同的类型,并且两者都参与模板参数推导,因此推导失败.

User defined conversions are not considered when deducing template arguments from function calls, and since the two arguments have different types in this case, and both are participating in template argument deduction, the deduction fails.

§14.8.1/6 [temp.arg.explicit]

如果参数类型不包含参与模板参数推导的 template-parameters ,则会对函数参数执行

隐式转换(第4节),以将其转换为相应的函数参数的类型.

Implicit conversions (Clause 4) will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter type contains no template-parameters that participate in template argument deduction.

§14.8.2.1/4 [温度超过]

... [注意:如14.8.1中所述,如果参数不包含 template-parameters 参与模板参数推导.除了上述列表中所述的转换之外,还允许此类转换. -尾注]

... [ Note: as specified in 14.8.1, implicit conversions will be performed on a function argument to convert it to the type of the corresponding function parameter if the parameter contains no template-parameters that participate in template argument deduction. Such conversions are also allowed, in addition to the ones described in the preceding list. —end note ]

您需要将iterator转换为const_iterator,或将模板参数明确指定为std::distance.

You'll need to convert the iterator to const_iterator, or specify the template argument to std::distance explicitly.

auto n = std::distance(it1, static_cast<decltype(it1)>(it2));

auto n = std::distance<decltype(it1)>(it1, it2);

当然,其他选项是在两种情况下都不使用auto并明确指定迭代器类型,或者在需要确保类型为vector::cbegin()和vector::cend()成员函数. >.

Other options are, of course, to not use auto and explicitly specify the iterator type in both cases, or use the vector::cbegin() and vector::cend() member functions when you need to ensure that the type is a const_iterator.

这篇关于自动它= vector.begin()结果类型不能转换为const_iterator的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆