Jump to content
  • Advertisement
Sign in to follow this  
incin

c++ template challenge

This topic is 3178 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Using the same technique as c++'s iostreams you can do things like this: obj << 1 << 2 << 3; To effectively call a function 3 times with each value. obj.Exec(1); obj.Exec(2); obj.Exec(3); This is easy! Can anyone devise a way to transform this: obj << 1 << 2 << 3; To this: obj.Exec(1,2); obj.Exec(3); ie. Pairing every two arguments into a single call. The only solution I can begin to think of would depend on destructors of temporaries, which would mess up the ordering. Anyone have a solution?

Share this post


Link to post
Share on other sites
Advertisement
struct Pair {
Pair(int a, int b) : a(a), b(b) {}
int a, b;
};

Foo & operator<<(Foo &f, const Pair & p) {
foo.op(p.a, p.b);
return f;
}

Foo foo;
foo << Pair(1,2) << Pair(2,3);

Share this post


Link to post
Share on other sites
Thanks for the reply, but the point was for the template to do the pairing for the user. Anything's possible if you can change the caller, but is it possible keeping the same syntax:
obj << 1 << 2 << 3;

Share this post


Link to post
Share on other sites
Well, you could do something like this (not compiled or tested):
struct Foo {
Foo() : cachedValue(0), valueCached(false) {}

void operator()(int value) {
if (valueCached) {
do_stuff(cachedValue, value);
valueCached = false;
} else {
cachedValue = value;
valueCached = true;
}
}
void do_stuff(int value1, int value2) { /*...*/ }

int cachedValue;
bool valueCached;
};

Foo& operator<<(Foo& foo, int value) {
foo(value);
return f;
}
This could probably be made a bit more elegant by using (e.g.) boost::optional.

Note that the cached value will 'roll over', so if you write (e.g.):
Foo foo;
foo << 1 << 2 << 3;
foo << 4 << 5 << 6;
The pairs that are processed will be (1,2), (3,4), and (5,6).

Just out of curiosity, what's the actual problem that you're trying to solve?

Share this post


Link to post
Share on other sites
The cached value idea is closer to what I want, but I didn't mention that the parameters aren't always integers.

The purpose of this was to improve performance.
Suppose you store some data with this overloaded operator, calling some function Store(). Each call to Store() has overhead for the function call, and for ensuring space requirements. So Store(x,y) is less than 75% of the cost of Store(x)+Store(y).

I could cache a void*/byte count, but that's going to fail with local variables if I don't clear the 'cache' prior to losing scope, ie:
fn(obj)
{
if (1)
{
int v=5;
obj << v;
}
}

It's likely there's not a great solution to this, and the performance gain probably isn't worth worrying about. But I thought there might be an elegant solution I was missing.

Share this post


Link to post
Share on other sites
Hi there,

If performance is your concern and you have to keep the syntax then how about using a macro to break the line up into more efficient code without the users knowledge.

-JonRambo

Share this post


Link to post
Share on other sites
Just out of curiosity: why would you want to do that? I think "a << 1 << 2 << 3 << 4" implicitly building pairs is confusing. I dislike using operators to such an extent, because the operator wasn't meant for that, it's syntactically confusing.

Share this post


Link to post
Share on other sites
I agree if the point was to make pairs, it wouldn't be intuitive. But the point was, to make, say 20 function calls under-the-hood instead of 40 effectively doing the same work but with less overhead.

Share this post


Link to post
Share on other sites
During the construction of the temporaries, you could build up a boost::mpl sequence of the types involved. When the first temporary is destroyed, process all of the "arguments", looking for pairs or N-tuples as required.

I don't know whether it's really worth the effort, though...

Share this post


Link to post
Share on other sites
Hello,

What you want to do is impossible. The best, closest thing you can do to intercept all the arguments at once and write less code is something like this:

foo _(1,2,3) or foo << _(1,2,3).
First case is a macro doing the same thing as
the second case which is a template function with variable argument number.
from that on you can return a template class to temporarily hold the arguments.


the operator << is a template itself taking that class. It should work but you have to write a hell lot of code and it doesn't worth it.
Edit:
There is another way: but it would requare to place your statement betwin {}
ex: { foo<<1<<2<<3 } this will cause the destruction of the object returned by the first operator << to be called. that object upon calling << can store the argument and return himself. When the destructor is called the operation can be performed on all the arguments.


Raxvan.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!