自动它= vector.begin()结果类型不能转换为const_iterator [英] auto it = vector.begin() resulting type is not convertible to const_iterator
问题描述
要求容器提供一个iterator
类型,该类型可以隐式转换为const_iterator
.鉴于此,我尝试使用auto
通过vector::begin()
初始化对象,并在RHS为const_iterator
的std::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_iterator
和iterator
.
从函数调用中推导模板参数时不考虑用户定义的转换,并且由于在这种情况下两个参数具有不同的类型,并且两者都参与模板参数推导,因此推导失败.
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::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屋!