此问题类似于
std::vector<bool>
,您希望提供一个代理,该代理的行为类似于引用,但也支持值语义。
但不同的是,涉及的类型没有限制,涉及到两个参考,各种各样的毛发都会弹出。以下是部分实现,它说明了您遇到的一些问题
#include<iterator>
#include<functional>
template<typename F, typename S, bool defined = true>
struct sfinae_difference_type {};
template<typename F, typename S>
struct sfinae_difference_type<F, S,
std::is_same_v<typename std::iterator_traits<F>::difference_type,
typename std::iterator_traits<S>::difference_type>>
{
using difference_type = typename std::iterator_traits<F>::difference_type;
};
template<typename F, typename S>
class pair_iterator : sfinae_difference_type<F, S>
{
using Fvalue_type = typename std::iterator_traits<F>::value_type;
using Svalue_type = typename std::iterator_traits<S>::value_type;
using Freference = typename std::iterator_traits<F>::reference;
using Sreference = typename std::iterator_traits<S>::reference;
F f;
S s;
public:
using value_type = std::pair<Fvalue_type, Svalue_type>;
struct reference
{
Freference first;
Sreference second;
reference() = delete;
reference(const reference& other) : first{other.first}, second{other.second} {}
reference& operator=(const reference& rhs)
{
first = rhs.first;
second = rhs.second;
return *this;
}
operator value_type() { return {f, s}; }
private:
reference(Freference f, Sreference s) : first{f}, second{s} {}
friend pair_iterator;
};
struct pointer
{
// similar to reference
};
pair_iterator() = default;
pair_iterator(const pair_iterator&) = default;
pair_iterator(F f, S s) : f{f}, s{s} {}
pair_iterator& operator++() { ++f; ++s; return *this; }
reference operator*() { return {*f, *s}; }
pointer operator->() { return {f.operator->(), s.operator->()}; }
bool operator==(const pair_iterator& other)
{
return f == other.f && s == other.s;
}
};
然后将其用作
#include<vector>
#include<list>
#include<iostream>
int main()
{
std::vector v{1, 2, 3, 4, 5};
std::list l{6, 7, 8, 9, 10};
pair_iterator begin{v.begin(), l.begin()}, end{v.end(), l.end()};
for(; begin != end; ++begin)
std::cout << begin->first << ' ' << begin->second << '\n';
}
Live
一些显而易见的问题:
-
实现是乏味的。拥有sfinae友好的类型别名和适当的代理需要大量的样板文件。
-
代理的语义可能令人困惑。复制/分配一个
reference
另一个意思?是什么
auto is_this_a_copy = *it
应该怎么做?
-
平等意味着什么?两个内部迭代器是否必须相等才能相等?这打破了与末端迭代器的比较。
所有这些都必须经过努力才能奏效,而且没有一个简单的答案。