具有复杂值类型的迭代器:与value_type和引用混淆
Iterators with complex value type: confusion with value_type and reference
我想创建一个自定义迭代器包装器,例如,enumerate
:给定一对类型T
的迭代器,它将返回一个可迭代的超过类型std::pair<const int, T&>
,其中该对的第一个元素将取值0,1,2,依此类推。
我在弄清楚我的迭代器应该value_type
和reference
什么时遇到问题。我想支持两种行为:
首先,引用基础序列的值:
for (auto& kv: enumerate(my_vec)) {
kv.second = kv.first;
}
(有点std::iota
);
其次,复制值:
std::vector<int> a{10, 20, 30};
auto copy = *enumerate(a).begin();
a[0] = 15;
std::cout << copy.first << " " << copy.second; // 0 10
我很困惑Iterator::operator*()
的返回类型应该是什么.如果std::pair<const int, T&>
则在第二个示例中不会复制值。如果它是std::pair<const int, T>
那么在第一个例子中,就不可能引用基础值。我应该做什么,应该value_type
什么,reference
和pointer
这种迭代器的typedefs?
这是我实现它的尝试。它支持引用,但不支持复制。
template<typename T>
struct Iterator {
using TT = typename std::iterator_traits<T>::value_type;
using value_type = std::pair<const int, TT>;
using reference = std::pair<const int&, typename std::iterator_traits<T>::reference>;
using pointer = value_type*;
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
std::pair<int, T> it;
Iterator(T iterator) : it(0, iterator) {}
bool operator==(const Iterator& other) const { return it.second == other.it.second; }
bool operator!=(const Iterator& other) const { return it.second != other.it.second; }
reference operator*() { return { it.first, *it.second }; }
Iterator& operator++() { ++it.first; ++it.second; return *this; }
};
附言我刚刚检查过,boost::适配器::索引遇到同样的问题并且不复制该值。
这个问题类似于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';
}
住
一些显而易见的问题:
- 实施是乏味的。拥有 sfinae 友好的类型别名和适当的代理需要大量的样板文件。
- 代理的语义可能会令人困惑。将一个
reference
复制/分配给另一个是什么意思?auto is_this_a_copy = *it
应该怎么做? - 平等是什么意思?两个内部迭代器是否必须相等才能相等?这打破了与结束迭代器的比较。
所有这些都必须敲定才能使其发挥作用,并且没有一个简单的答案。
相关文章:
- 瓦尔格林德:数学函数"Conditional jump or move depends on uninitialised value(s)"
- 使用 [] 运算符时"binding reference of type discards qualifiers"
- 为什么static_assert错误:即使我传递常量"expression must have a constant value"?
- 在 QVector<std::unique_ptr 上使用 std::find<Type>>
- 在类型和包装器之间reinterpret_cast是否安全<Type>?
- 使用 cmake 的 Linux 终端上的"Conversion to non-scalar type is requested"错误
- 控制到达非空函数clang(-Wreturn-type)的末尾
- 为什么我会" void value not ignored as it ought to be"?
- std::unordered_map 类型对象声明期间出现"field has incomplete type"错误
- 方法错误"not all control paths return a value"和方法不返回值
- 将系数存储在头文件的数组中("does not name a type"错误)
- 尝试打开 ifstream 时出现"Incomplete type"错误
- C++/SDL "initial value of reference to a non-const must be an lvalue"
- 将成员函数作为构造函数参数调用时出错 "Variable is not a type name"
- 在"结构提升::enable_if<提升::is_pod<T>,无效>"中没有名为"type"的类型
- 如何修复" State Error (active) E0513 a value of type "const wchar_t *" cannot be assigned to an entity o
- "a value of type " void (exeCallback::*)(int) " cannot be assigned to an entity of type " void (*)(
- cmake -D <var>:<type>=<value> 参数"-D"是什么意思
- 没有用于初始化'value type'的匹配构造函数
- new(size, value) Type[0]返回的指针是否合法,是否可以用来构建数组?