如何实施运营商->;对于按需构造其值的迭代器? 我有一个C++类,它的作用就像容器:它有 siz()/和运算符[]成员函数。“在”容器中存储的值是std::tuple对象。然而,容器实际上并不在内存中保存元组;相反,它基于以不同形式存储的底层数据按需构建它们 std::tuple<int, int, int> MyContainer::operator[](std::size_t n) const { // Example: draw corresponding elements from parallel arrays return { underlying_data_a[n], underlying_data_b[n], underlying_data_c[n] }; }
但是,更新存储的值需要迭代器检查其当前索引是否小于容器的大小,以便过期迭代器不会通过访问基础数组的末尾而导致未定义的行为。这增加了(少量)运行时开销——当然,这还不足以使解决方案变得不切实际,但它感觉有点不雅观。迭代器实际上不需要存储任何东西,只需要一个指向它正在迭代的容器及其当前位置的指针 对于按需构造值的迭代器类型,是否有一种干净、成熟的方法来支持如何实施运营商->;对于按需构造其值的迭代器? 我有一个C++类,它的作用就像容器:它有 siz()/和运算符[]成员函数。“在”容器中存储的值是std::tuple对象。然而,容器实际上并不在内存中保存元组;相反,它基于以不同形式存储的底层数据按需构建它们 std::tuple<int, int, int> MyContainer::operator[](std::size_t n) const { // Example: draw corresponding elements from parallel arrays return { underlying_data_a[n], underlying_data_b[n], underlying_data_c[n] }; },c++,c++11,iterator,operator-overloading,C++,C++11,Iterator,Operator Overloading,但是,更新存储的值需要迭代器检查其当前索引是否小于容器的大小,以便过期迭代器不会通过访问基础数组的末尾而导致未定义的行为。这增加了(少量)运行时开销——当然,这还不足以使解决方案变得不切实际,但它感觉有点不雅观。迭代器实际上不需要存储任何东西,只需要一个指向它正在迭代的容器及其当前位置的指针 对于按需构造值的迭代器类型,是否有一种干净、成熟的方法来支持运算符->?其他开发人员将如何做这种事情 (请注意,我根本不需要支持操作符->——我实现迭代器的主要目的是让容器可以通过C++11进行遍历。“”循
运算符->
?其他开发人员将如何做这种事情
(请注意,我根本不需要支持
操作符->
——我实现迭代器的主要目的是让容器可以通过C++11进行遍历。“”循环,并且std::tuple
没有任何通常希望通过->
访问的成员。但是我还是希望正确地建模迭代器概念;否则我感觉像是在偷工减料。或者我应该不麻烦吗?)下面是一个示例,它依赖于这样一个事实:在返回指针之前,操作符->
会被重复应用。我们让Iterator::operator->
将包含的对象作为临时对象返回。这会导致编译器重新应用运算符->
。然后,我们让Contained::operator->
只返回一个指向自身的指针。请注意,如果我们不想将操作符->
放在包含的动态对象中,我们可以将其包装在一个helper对象中,该对象返回指向内部包含对象的指针
#include <cstddef>
#include <iostream>
class Contained {
public:
Contained(int a_, int b_) : a(a_), b(b_) {}
const Contained *operator->() {
return this;
}
const int a, b;
};
class MyContainer {
public:
class Iterator {
friend class MyContainer;
public:
friend bool operator!=(const Iterator &it1, const Iterator &it2) {
return it1.current_index != it2.current_index;
}
private:
Iterator(const MyContainer *c, std::size_t ind) : container(c), current_index(ind) {}
public:
Iterator &operator++() {
++current_index;
return *this;
}
// -> is reapplied, since this returns a non-pointer.
Contained operator->() {
return Contained(container->underlying_data_a[current_index], container->underlying_data_b[current_index]);
}
Contained operator*() {
return Contained(container->underlying_data_a[current_index], container->underlying_data_b[current_index]);
}
private:
const MyContainer *const container;
std::size_t current_index;
};
public:
MyContainer() {
for (int i = 0; i < 10; i++) {
underlying_data_a[i] = underlying_data_b[i] = i;
}
}
Iterator begin() const {
return Iterator(this, 0);
}
Iterator end() const {
return Iterator(this, 10);
}
private:
int underlying_data_a[10];
int underlying_data_b[10];
};
int
main() {
MyContainer c;
for (const auto &e : c) {
std::cout << e.a << ", " << e.b << std::endl;
}
}
#包括
#包括
包含的类{
公众:
包含(inta_uu,intb_u):a(a_u),b(b_u){
常量包含*运算符->(){
归还这个;
}
常数INTA,b;
};
类霉菌容器{
公众:
类迭代器{
朋友级MyContainer;
公众:
友元布尔运算符!=(常量迭代器&it1,常量迭代器&it2){
返回it1.current\u index!=it2.current\u index;
}
私人:
迭代器(const MyContainer*c,std::size\u t ind):容器(c),当前索引(ind){
公众:
迭代器和运算符++(){
++当前_指数;
归还*这个;
}
//->将重新应用,因为这将返回一个非指针。
包含运算符->(){
包含的返回(容器->基础_数据_a[当前_索引]、容器->基础_数据_b[当前_索引]);
}
包含运算符*(){
包含的返回(容器->基础_数据_a[当前_索引]、容器->基础_数据_b[当前_索引]);
}
私人:
常量容器*常量容器;
标准:当前索引的大小;
};
公众:
MyContainer(){
对于(int i=0;i<10;i++){
基础数据\u a[i]=基础数据\u b[i]=i;
}
}
迭代器begin()常量{
返回迭代器(this,0);
}
迭代器end()常量{
返回迭代器(这个,10);
}
私人:
int基础_数据_a[10];
int基础_数据_b[10];
};
int
main(){
霉素c;
用于(常数自动和电气:c){
std::cout模板
结构伪ptr{
T;
T运算符*()&&{return T;}
T*运算符->(){return&T;}
};
然后
structbar{intx,y;};
结构条迭代器:std::迭代器{
// ...
伪_ptr运算符->()常量{return{**this};}
// ...
};
这取决于->
的工作方式
指针的ptr->b
的ptr
只是(*ptr).b
否则,它被定义为(ptr.operator->())->b
。如果operator->
不返回指针,它将递归计算
上面的pseudo_ptr
为您提供了一个T
副本的包装器
但是,请注意,生命周期扩展并没有真正起作用。结果是脆弱的。运算符->
不必返回指针。它只需返回一些可以应用*
的内容。嗯,这样我就可以返回一个“假指针”,其中包含一个值,并在“取消引用”时返回该值?我不确定这是否比将值存储在迭代器本身更尴尬。:-),但至少(使用内联)会有零运行时开销。在任何情况下,要建模ForwardIterator
,必须满足以下要求:“如果a和b都是可取消引用的,那么a==b当且仅当*a和*b绑定到同一个对象。“这通常意味着返回代理或包含自身值的迭代器只能是InputIterators@KerrekSB,看起来返回的值实际上必须支持->
,而不是*
。一个具有自己的运算符->
的伪指针类(返回真实指针)可以工作,但是在伪指针中只实现操作符*()
是不起作用的。[over.ref]/1:“表达式x->m
对于类型为t
的类对象x
如果t::operator->()
存在,并且如果操作员被操作员选择为最佳匹配功能
#include <cstddef>
#include <iostream>
class Contained {
public:
Contained(int a_, int b_) : a(a_), b(b_) {}
const Contained *operator->() {
return this;
}
const int a, b;
};
class MyContainer {
public:
class Iterator {
friend class MyContainer;
public:
friend bool operator!=(const Iterator &it1, const Iterator &it2) {
return it1.current_index != it2.current_index;
}
private:
Iterator(const MyContainer *c, std::size_t ind) : container(c), current_index(ind) {}
public:
Iterator &operator++() {
++current_index;
return *this;
}
// -> is reapplied, since this returns a non-pointer.
Contained operator->() {
return Contained(container->underlying_data_a[current_index], container->underlying_data_b[current_index]);
}
Contained operator*() {
return Contained(container->underlying_data_a[current_index], container->underlying_data_b[current_index]);
}
private:
const MyContainer *const container;
std::size_t current_index;
};
public:
MyContainer() {
for (int i = 0; i < 10; i++) {
underlying_data_a[i] = underlying_data_b[i] = i;
}
}
Iterator begin() const {
return Iterator(this, 0);
}
Iterator end() const {
return Iterator(this, 10);
}
private:
int underlying_data_a[10];
int underlying_data_b[10];
};
int
main() {
MyContainer c;
for (const auto &e : c) {
std::cout << e.a << ", " << e.b << std::endl;
}
}
template<class T>
struct pseudo_ptr {
T t;
T operator*()&&{return t;}
T* operator->(){ return &t; }
};
struct bar { int x,y; };
struct bar_iterator:std::iterator< blah, blah >{
// ...
pseudo_ptr<bar> operator->() const { return {**this}; }
// ...
};