我尝试了两种方法来实现从const_iterator到iterator的转换。所有迭代器都基于boost/iterator
。
第一种方法定义了一个iterator<T>
类。 iterator<const T>
将代表const_iterator
。 iterator<T>
具有一个转换运算符,返回一个iterator<const T>
。但这在模板函数中会失败,因为在模板实例化期间不能进行任何类型转换。
第二种方法理论上是可行的。但在实践中,我需要为iterator<T>
定义每个方法:
#include <iostream>
#include <boost/iterator/iterator_adaptor.hpp>
#include <vector>
template<typename Container>
class Cit
: public boost::iterator_adaptor<
Cit<Container>, // Derived
typename Container::const_iterator, // Base
const typename Container::value_type> {
using self_type = Cit<Container>;
friend class boost::iterator_core_access;
public:
explicit Cit(typename Container::const_iterator it)
: self_type::iterator_adaptor_(it) {}
};
template<typename Container>
class It : public Cit<Container> {
protected:
using reference = typename Container::reference;
using self_type = It<Container>;
using Base = Cit<Container>;
public:
explicit It(typename Container::iterator it)
: Base(it) {}
reference operator*() const {
return const_cast<reference>(Base::operator*());
}
// Try to hide every method from Cit<Container>
// ...
// ...
// ...
// ... oh well.
private:
friend class boost::iterator_core_access;
};
// A template function
template<typename Container>
void foo(Cit<Container> it_begin,
Cit<Container> it_end) {
for (auto it = it_begin; it != it_end; ++it) {
std::cout << *it << "\n";
}
}
int main() {
typedef std::vector<int> Container;
Container v = {0, 1, 2, 3}; // content array
It<Container> it_begin(v.begin());
It<Container> it_end(v.end());
// Assert It can implicitly convert to Cit even during template
// instantiation.
foo(it_begin, it_end);
return 0;
}
这似乎抵消了使用boost/iterator的好处。
是否有更好的方法来使用boost/iterator创建iterator和const_iterator?
以下是第一种方法:
#include <iostream>
#include <boost/iterator/iterator_adaptor.hpp>
#include <vector>
template<typename Container>
class It
: public boost::iterator_adaptor<
It<Container>, // Derived
typename Container::const_iterator, // Base
typename std::conditional<std::is_const<Container>::value,
const typename Container::value_type,
typename Container::value_type
>::type // Value
> {
using self_type = It<Container>;
friend class boost::iterator_core_access;
public:
explicit It(typename Container::const_iterator it)
: self_type::iterator_adaptor_(it) {}
};
template <typename C> using Cit = It<const C>;
// A template function
template<typename Container>
void foo(Cit<Container> it_begin,
Cit<Container> it_end) {
for (auto it = it_begin; it != it_end; ++it) {
std::cout << *it << "\n";
}
}
int main() {
typedef std::vector<int> Container;
Container v = {0, 1, 2, 3}; // content array
It<Container> it_begin(v.begin());
It<Container> it_end(v.end());
// Assert It can implicitly convert to from Cit to It even
// during template instantiation.
foo(it_begin, it_end);
return 0;
}
错误信息:
error: no matching function for call to ‘foo(It<std::vector<int> >&, It<std::vector<int> >&)’
foo(it_begin, it_end);
^
main.cpp:26:6: note: candidate: template<class Container> void foo(Cit<Container>, Cit<Container>)
void foo(Cit<Container> it_begin,
^~~
main.cpp:26:6: note: template argument deduction/substitution failed:
main.cpp:41:25: note: types ‘const C’ and ‘std::vector<int>’ have incompatible cv-qualifiers
foo(it_begin, it_end);