Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
206 views
in Technique[技术] by (71.8m points)

c++ - How to reduce redundant code when adding new c++0x rvalue reference operator overloads

I am adding new operator overloads to take advantage of c++0x rvalue references, and I feel like I'm producing a lot of redundant code.

I have a class, tree, that holds a tree of algebraic operations on double values. Here is an example use case:

tree x = 1.23;
tree y = 8.19;
tree z = (x + y)/67.31 - 3.15*y;
...
std::cout << z; // prints "(1.23 + 8.19)/67.31 - 3.15*8.19"

For each binary operation (like plus), each side can be either an lvalue tree, rvalue tree, or double. This results in 8 overloads for each binary operation:

// core rvalue overloads for plus:
tree operator +(const tree& a, const tree& b);
tree operator +(const tree& a, tree&&      b);
tree operator +(tree&&      a, const tree& b);
tree operator +(tree&&      a, tree&&      b);

// cast and forward cases:
tree operator +(const tree& a, double      b) { return a + tree(b); }
tree operator +(double      a, const tree& b) { return tree(a) + b; }
tree operator +(tree&&      a, double      b) { return std::move(a) + tree(b); }
tree operator +(double      a, tree&&      b) { return tree(a) + std::move(b); }

// 8 more overloads for minus

// 8 more overloads for multiply

// 8 more overloads for divide

// etc

which also has to be repeated in a way for each binary operation (minus, multiply, divide, etc).

As you can see, there are really only 4 functions I actually need to write; the other 4 can cast and forward to the core cases.

Do you have any suggestions for reducing the size of this code?

PS: The class is actually more complex than just a tree of doubles. Reducing copies does dramatically improve performance of my project. So, the rvalue overloads are worthwhile for me, even with the extra code. I have a suspicion that there might be a way to template away the "cast and forward" cases above, but I can't seem to think of anything.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

Just a quick late answer: If the class in question is moveable, the move is very cheap, and you would always move from all the arguments if you can, then passing the arguments by value might be an option:

tree operator +(tree      a, tree      b);

If tree is moveable and an rvalue ref is passed as the actual argument, then the arguments to the function will be initialized with tree's move constructor where possible, else the copy constructor. Then, the function can do whatever it wants with its arguments in the appropriate way (like, say, moving their internals around).

It does incur an extra move when passing an rvalue reference argument compared with the lots-of-overloads version, but I think it's generally better.

Also, IMO, tree && arguments should maybe accept lvalues via a temporary copy, but this is not what any compilers currently do, so it's not very useful.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...