Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何实施运营商->;对于按需构造其值的迭代器? 我有一个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 - Fatal编程技术网

如何实施运营商->;对于按需构造其值的迭代器? 我有一个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}; }
  // ...
};