【发布时间】:2014-09-30 20:06:01
【问题描述】:
容器需要提供iterator 类型,该类型可以隐式转换为const_iterator。鉴于此,我尝试使用auto 通过vector::begin() 初始化对象,并在std::distance 中使用生成的对象,其中RHS 是const_iterator。这是行不通的。这是一个完整的例子:
#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)下编译会产生:
[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,我不确定我是否理解为什么需要这样做。
为什么auto 在这种情况下会推导出一个不可转换为const_iterator 的类型?
【问题讨论】:
-
我们不能将此代码缩减为:gist.github.com/sharth/fbe0cddbe9a200d82b89
-
它是,但你不投它。没有进行隐式转换来尝试匹配重载
-
@sp2danny:我想这就是我的答案。
-
在您输入问题的标题之前,您是否没有注意到编译器在下一行将
auto it = foo.begin()转换为const_iterator并且没有抱怨它? -
在不需要修改时考虑使用
cbegin和cend而不是begin和end。
标签: c++ c++11 auto implicit-conversion