仅覆盖自定义数据结构的迭代器的operator *() [英] Override only operator*() of iterator of a custom datastructure
问题描述
我有一个数组类 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>
/ pre>
...
MyArray< B>测试;
for(C ele:test | boost :: adapter :: transformed(convertBToC)){
// something ...
}
判断自己有多少改善。也许更好地把
operator |
调用在一个新的MyArray
的成员函数中。I have an array class
MyArray
withMyArray
.
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
andC
.
I have a converter fromB
toC
namedconvertBToC(B)
.Now, I want a new datastructure (named
MyArray2
) that :-
- act mostly like
MyArray<B>
.... - except that function
operator*()
ofMyArray2
's iterator returnC
instead ofB
- the
C
that is returned, convert fromB
usingconvertBToC(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 (becauseMyIterator
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 fromMyArray<B>
Override:begin()
orend()
- returnMyIterator2
.MyIterator2
derived fromMyIterator<B>
Override:operator*()
- returnC
(usingconvertBToC()
).
Disadvantage:
- Dirty - I have to create 2 classes just to override only 1 function.
MyArray2.h
code contains the wordMyIterator<T>
.
Solution 2 (lambda)
Create only 1 class :-
MyArray2
derived fromMyArray<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屋!