Operator Overloading with Chaining
I would like to overload << operator for chaining like below
function1(param1, param2)<< obj2 << obj3 << string4
function1 would return an object.
What I want to do is after string4, I need to call a function using param1, param2.
My questions will be
How do I know string4 is the last parameters in the expression and hence I need to call another function2 using param1 and param2 or it isn't possible to do so?
How do I pass param1 and param2开发者_如何学Python to the function to be called? I could not store the param1 and param2 in the object as it is a multithreaded.
Thanks.
You can return a helper object from function1
by value which calls function2
in it's destructor.
Consider this example:
#include <iostream>
using namespace std;
void function2( int i, int j ) {
cout << "function2 called with " << i << " and " << j << endl;
}
struct Function2Caller {
Function2Caller( int param1, int param2 ) : m_param1( param1 ), m_param2( param2 ) {}
~Function2Caller() { function2( m_param1, m_param2 ); }
int m_param1, m_param2;
};
Function2Caller &operator<<( Function2Caller &obj, int x ) {
cout << "Streaming " << x << endl;
return obj;
}
Function2Caller function1( int i, int j ) {
cout << "function1 called with " << i << " and " << j << endl;
return Function2Caller( i, j );
}
int main() {
function1( 2, 3 ) << 4 << 6;
}
This program prints
function1 called with 2 and 3 Streaming 4 Streaming 6 function2 called with 2 and 3
The idea is that at the end of your line, the Function2Caller
object goes out of scope and the destructor then does its work.
Please note that when implementing this you should probably forbid copying of Function2Caller objects and make function1
the only one who can call the Function2Caller
constructor.
As Frerich Raabe noted, one possible solution is to use the destructor of a temporary object. It does impose, however, that you will somehow NEED to call all the arguments inline, thus prohibiting the following syntax:
auto stream = function1(param1, param2) << param3;
stream << param4;
stream << stringG; // call here
The IO Stream library in the Standard Library circumvents the issue by using a global object as a "marker": std::endl
. This could be another option.
Note that if you go the marker way, you can lift the requirement of no copying.
In the end, it's more a matter of design that a matter of implementation, so it's your call.
class Stream
{
public:
struct Marker {};
static Marker End;
Stream(type1, type2);
void operator<<(Marker) const { function2(m1,m2); }
Stream& operator<<(...);
private:
type1 m1;
type2 m2;
};
Have fun :)
How do I know string4 is the last parameters in the expression and hence I need to call the function using param1 and param2 or it isn't possible to do so?
function1(param1, param2)<< obj2 << obj3 << string4
doesn't do what you think it does. Here function1
is evaluated first, the resulting object is used to call operator<<
with obj2
as an argument and so on...
If you want to call function1
at the end, it should occur after you have called operator<<
with string4
as an argument.
How do I pass param1 and param2 to the function to be called? I could not store the param1 and param2 in the object as it is a multithreaded.
Your op<<
should return an object of type T which has op()
defined so that you can all it with param1
and param2
at the very end.
If function1
is returning something (say an int
), you should be able to delay al computations until it's value is used. . You should return an object that can be converted to an int
(by implementing int operator int()
as a member function).
In function1
's implementation you construct it. The object will also implement <<
. In that member function that does the conversion, you use all the values you collected as parameters and passed in with the <<
operator.
You pass a functor at the end its easier this way
class myfun {
public:
void operator()(const string& param1, const string& param2, const string& values) const {
std::cout << "param1: " << param1 << "param2: " << param2 << " value: " << values << std::endl;
}
};
class A {
string m_param1, m_param2;
string values;
public:
A(string param1, string param2):m_param1(param1), m_param2(param2) { }
A& operator << (const string& str) {
values += str;
return *this;
}
A& operator << (const myfun& myfun) {
myfun(m_param1, m_param2, values);
return *this;
}
};
A fun(string param1, string param2) {
return A(param1, param2);
};
int main() {
fun("a", "b") << "xyz" << myfun();
return 0;
}
精彩评论