C++在函数中从back_insert_iterator转换为迭代器
C++ cast from back_insert_iterator to iterator within functors
我正在尝试实现一种复制运算符。目的是有两个类:一个浏览容器,另一个用它做一些事情。browse类还(出于某种原因)在outout容器上维护一个迭代器,而另一个可以用它计算增量。
不幸的是,编译器似乎无法将back_insert_iterator转换为输出迭代器。为什么?
#include <iostream>
#include <iterator>
#include <vector>
typedef std::vector<int> Vec;
// An operator that copy an item onto another
template< class TIN, class TOUT >
class DoCopy
{
TOUT operator()( const typename TIN::iterator i_in, const typename TOUT::iterator i_out )
{
const typename TOUT::iterator i_incr = i_out;
(*i_incr) = (*i_in);
std::advance( i_incr, 1 );
return i_incr;
}
};
// The class that iterate over a container, calling an operator for each item
template< class TIN, class TOUT >
class Browse
{
public:
// We keep a reference to the operator that really do the job
DoCopy<TIN,TOUT> & _do;
Browse( DoCopy<TIN,TOUT> & op ) : _do(op) {}
// Iterate over an input container
TOUT operator()(
const typename TIN::iterator in_start,
const typename TIN::iterator in_end,
const typename TOUT::iterator out_start
)
{
TOUT i_out = out_start;
for( TIN i_in = in_start; i_in != in_end; ++i_in ) {
// it is not shown why here, but we DO want the operator to increment i_out
i_out = _do(i_in, i_out);
}
}
};
int main()
{
// in & out could be the same type or a different one
Vec in;
Vec out;
DoCopy<Vec,Vec> do_copy;
Browse<Vec,Vec> copy(do_copy);
std::back_insert_iterator< Vec > insert_back(out);
// Here, g++ cannot find the corresponding function :
copy( in.begin(), in.end(), insert_back );
}
g++编译失败,出现以下错误:
$ g++ test.cpp && ./a.out
test.cpp: In function ‘int main()’:
test.cpp:54:49: erreur: no match for call to ‘(Browse<std::vector<int>, std::vector<int> >) (std::vector<int>::iterator, std::vector<int>::iterator, std::back_insert_iterator<std::vector<int> >&)’
test.cpp:22:11: note: candidate is:
test.cpp:30:18: note: TOUT Browse<TIN, TOUT>::operator()(typename TIN::iterator, typename TIN::iterator, typename TOUT::iterator) [with TIN = std::vector<int>, TOUT = std::vector<int>, typename TIN::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >, typename TOUT::iterator = __gnu_cxx::__normal_iterator<int*, std::vector<int> >]
test.cpp:30:18: note: no known conversion for argument 3 from ‘std::back_insert_iterator<std::vector<int> >’ to ‘__gnu_cxx::__normal_iterator<int*, std::vector<int> >’
这是问题的主要来源:std::back_insert_iterator< V<T> >
和std::vector<T>::iterator
在它们的继承树中没有直接关联:
std::vector<T>::iterator
是__normal_iterator<T>
(没有其他超类)(std::vector<T>::iterator
的stl_vector.h
和__normal_iterator
的stl_iterator.h
)std::back_insert_iterator< V<T> >
是一个迭代器(没有其他的超类)(std::back_insert_iterator
看stl_iterator.h
,std::iterator
看stl_iterator_base_types.h
)
它们不能向任何方向转换。
因此,第二个模板参数应该直接是std::back_insert_iterator
或iterator<>
,其中第一个参数表示它是输出运算符。
我认为std::advance( iterator, 1 )
是指++iterator
,它是迭代器进入下一个元素的标准方式。
此外,out迭代器不应该是const
,否则它们不会实现做作的operator=
。
第38行,i_in
的类型应该是typename TIN::iterator
,而不是TIN
。Browseoperator()
还必须返回out迭代器。
最后的代码如下:
#include <iostream>
#include <iterator>
#include <vector>
typedef std::vector<int> Vec;
// An operator that copy an item onto another
template< class TIN, class TOUT >
class DoCopy
{
public:
TOUT operator()( const typename TIN::iterator i_in, const TOUT i_out )
{
TOUT i_incr = i_out;
(*i_incr) = (*i_in);
//std::advance( i_incr, 1 );
++i_incr;
return i_incr;
}
};
// The class that iterate over a container, calling an operator for each item
template< class TIN, class TOUT >
class Browse
{
public:
// We keep a reference to the operator that really do the job
DoCopy<TIN,TOUT> & _do;
Browse( DoCopy<TIN,TOUT> & op ) : _do(op) {}
// Iterate over an input container
TOUT operator()(
const typename TIN::iterator in_start,
const typename TIN::iterator in_end,
const TOUT out_start
)
{
TOUT i_out = out_start;
for( typename TIN::iterator i_in = in_start; i_in != in_end; ++i_in ) {
// it is not shown why here, but we DO want the operator to increment i_out
i_out = _do(i_in, i_out);
}
return i_out;
}
};
int main()
{
// in & out could be the same type or a different one
Vec in;
in.push_back(1);
in.push_back(3);
in.push_back(3);
in.push_back(7);
Vec out;
DoCopy<Vec, std::back_insert_iterator<Vec> > do_copy;
Browse<Vec, std::back_insert_iterator<Vec> > copy(do_copy);
std::back_insert_iterator< Vec > insert_back(out);
// Here, g++ cannot find the corresponding function :
copy( in.begin(), in.end(), insert_back );
for( unsigned i = 0, s = out.size(); i < s; ++i )
{
std::cout << out[i] << " ";
}
std::cout << std::endl;
}
感谢clang++,它使C++错误更加清晰。
相关文章:
- Insert函数不适用于2 if语句C++
- 如何在C++向量中奇数元素前面加上值-1,我在使用insert函数时遇到了问题
- 在调试模式下引发C++ "deque iterator not dereferencable"异常
- std::iterator::reference 必须是引用吗?
- 为什么 gcc 会给我可能未初始化的警告 deque::insert 带有过滤范围
- 为什么unordered_set<string::iterator>不起作用?
- 当通知迭代器参数初始化为空列表的开头时,list::insert 行为是什么?
- 造成致命错误:boost/fusion/iterator/equal_to.hpp 没有这样的文件或目录
- Visual accept std::string from std::byte iterator
- 为什么使用 <uint8_t>MSVC 2015 编译器的 std::vector::insert 比 std::copy 快 5 倍?
- 如果迭代器没有因插入而无效,则使用std::find和C::insert()是线程安全的
- 与C++std::map::insert行为相比,C#排序字典的效率
- 什么是"std::set<int,int>::iterator"?
- std::list 的两个 insert() 方法签名之间的实现差异
- 从 std::vector 中删除项目时"Iterator not incrementable"
- 如何从 boost::container::vector<std::string>::iterator 访问索引和对象?
- 为什么 std::set::erase 与 std::set::insert 不一致?
- 空集"Out of bound iterator"
- 编译器如何区分"vector::insert"的两种变体?
- std::map 在 [] 上调用默认构造函数,在 insert() 上调用复制构造函数