仅覆盖自定义数据结构的迭代器的operator *() [英] Override only operator*() of iterator of a custom datastructure

查看:150
本文介绍了仅覆盖自定义数据结构的迭代器的operator *()的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个数组类 MyArray MyArray

为简单起见,这是整个代码。



当前代码



  #include< iostream> ; 
使用命名空间std;
template< class T> MyArray类
template< class T> class MyIterator {
public:int index = 0;
public:MyArray< T> * myArray;
public:MyIterator< T> operator ++(){
index ++;
return * this;
}
public:T& operator *(){
return myArray-> database [index];
}
public:friend bool operator!=(MyIterator< T> b,MyIterator< T> c){
return b.index!= c.index;
}
};
template< class T> class MyArray {
public:T database [5];
public:MyArray(){
数据库[2] = 3; //只是填写一些东西来测试
}
public:MyIterator< T> begin(){
MyIterator< T> ; r.index = 0; r.myArray = this;
return r;
}
public:MyIterator< T> end(){
MyIterator< T> ; r.index = 5; r.myArray = this;
return r;
}
};

这是它的用法: -

  int main(){
MyArray< int>测试; (int ele:test)
{
std :: cout<<<< std :: endl;
}
return 0;
}



问题/要求



我有具体的类,假设他们的名字是 B C 。 br>
我将一个转换器 B C 命名为 convertBToC(B)



现在,我想要一个新的数据结构(名为 MyArray2 ): -




  • 主要类似于 MyArray< B> ....

  • 除了函数 operator *() MyArray2 的迭代器返回 C 而不是 B

  • <转换为 C ,使用 convertBToC(B)


这是我想要的用法(#1 ): -

  MyArray2测试; 
//test.push_back(B()); //使用像MyArray< B> (C c:test){//C,而不是B
....关于c的逻辑

}

上面的代码可以像我这样称呼: -

  MyArray< B>阿尔(b& b:arr)
{
C c = convertBToC(b); //< - 我想隐藏这行
....逻辑关于c....
}

问题:如何编写 MyArray2



条件



我想要一个解决方案: - (按优先级排序)




  • 高效(不使用 std :: function 及其家庭)

  • 不直接引用 MyIterator (因为 MyIterator 是一个内部类)
  • 可爱(低数量的语句/行,可读)

  • 最小更改为 MyArray< T> (如果有)



最相关的问题是这里,但是它提到了 std :: vector



我可怜的解决方案



解决方案1(2x继承)



创建2个类: -




  • MyArray2 派生自 MyArray< B>

    覆盖: begin() end() - 返回我的Iterator2


  • MyIterator2 派生自 MyIterator< B>

    覆盖: operator *() - 返回 C (使用 convertBToC())。




缺点:




  • 肮脏 - 我必须创建2个类只是为了仅覆盖1个功能。

  • MyArray2.h 代码包含单词 MyIterator< T>



解决方案2(lambda)



仅创建1类: / p>


  • MyArray2 派生自 MyArray< B>

    新功能 iterate(): -



以下是 iterate()的草案: -

 模板< typename F> MyArray2 :: iterate(F lamdbaFunction){
for(B b:MyArray< B>){
C c = convertBToC(b);
lamdbaFunction(c);
}
}

使用情况必须从#1 为...(#2

  MyArray2 arr; 
自动lambdaF = [&](C c){
....逻辑关于c....
}
arr.iterateElement(lambdaF);

Disadvantage




  • 有时会破坏可读性。 (Lambda有时更难阅读)

  • 它限制编码风格。 (有时,我喜欢基于范围的循环。)


解决方案

另一种方法是使用升压范围适配器,特别是 boost :: adapters :: transformed

  #include< boost / range / adapter / transformed.hpp> 
...

MyArray< B>测试;
for(C ele:test | boost :: adapter :: transformed(convertBToC)){
// something ...
}
/ pre>

判断自己有多少改善。也许更好地把 operator | 调用在一个新的 MyArray 的成员函数中。


I have an array class MyArray with MyArray.
For simplicity, this is the whole code. It works OK.

Current code

#include <iostream>
using namespace std;
template<class T> class MyArray;
template<class T>class MyIterator{
    public: int index=0;
    public: MyArray<T>* myArray;
    public: MyIterator<T> operator++(){
        index++;
        return *this;
    }
    public: T& operator*(){
        return myArray->database[index];
    }
    public: friend bool operator!=(MyIterator<T> b,MyIterator<T> c){
        return b.index!=c.index;
    }
};
template<class T>class MyArray{
    public: T database[5];
    public: MyArray(){
        database[2]=3; //just fill with something to test
    }
    public: MyIterator<T> begin(){
        MyIterator<T> r;  r.index=0; r.myArray=this;
        return r;
    }
    public: MyIterator<T> end(){
        MyIterator<T> r;  r.index=5; r.myArray=this;
        return r;
    }
};

Here is its usage :-

int main() {
    MyArray<int> test;
    for(int ele:test){
        std::cout<<ele<<std::endl;
    }
    return 0;
}

Problem / requirement

I have specific classes, let's say their names are B and C.
I have a converter from B to C named convertBToC(B).

Now, I want a new datastructure (named MyArray2) that :-

  • act mostly like MyArray<B> ....
  • except that function operator*() of MyArray2's iterator return C instead of B
  • the C that is returned, convert from B using convertBToC(B).

This is the usage that I wished for (#1) :-

MyArray2 test;
//test.push_back(B());  //used like "MyArray<B>"
for(C c:test){          //"C", not "B"
    .... logic about "c" ....  
}  

The above code would work as if I call it like :-

MyArray<B> arr;   
for(B& b: arr){
    C c= convertBToC(b);   //<-- I want to hide this line
    .... logic about "c" .... 
}

Question: How to code MyArray2?

Criteria

I want a solution that :- (sorted by priority)

  • efficient (not use std::function and its family)
  • not refer to MyIterator directly (because MyIterator is an internal class)
  • cute (low amounts of statement/line, readable)
  • minimum change to MyArray<T> (if any)

The most related question is here, but it mentions about std::vector.

My poor solutions

Solution 1 (2x inheritance)

Create 2 classes :-

  • MyArray2 derived from MyArray<B>
    Override: begin() or end() - return MyIterator2.

  • MyIterator2 derived from MyIterator<B>
    Override: operator*() - return C (using convertBToC()).

Disadvantage:

  • Dirty - I have to create 2 classes just to override only 1 function.
  • MyArray2.h code contains the word MyIterator<T>.

Solution 2 (lambda)

Create only 1 class :-

  • MyArray2 derived from MyArray<B>
    new function: iterate() :-

Here is the draft of iterate() :-

template<typename F> MyArray2::iterate( F lamdbaFunction ){
    for(B b: MyArray<B>){
         C c= convertBToC(b);
         lamdbaFunction(c);
    }
}

The usage have to be changed from #1 to be ... (#2)

MyArray2 arr;   
auto lambdaF=[&](C c){     
    .... logic about "c" .... 
}
arr.iterateElement(lambdaF);

Disadvantage

  • It sometimes destroy readability. (Lambda sometimes harder to read)
  • It limits coding style. (Sometimes, I prefer range-based loop.)

解决方案

Another approach would be to use Boost range adaptors, specifically boost::adaptors::transformed.

#include <boost/range/adaptor/transformed.hpp>
...

MyArray<B> test;
for(C ele : test | boost::adaptor::transformed(convertBToC)) {
    // something...
}

Judge how much of an improvement it is yourself. Maybe better put the operator| call inside a new MyArray's member function.

这篇关于仅覆盖自定义数据结构的迭代器的operator *()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆