-
July 28th, 2009, 12:08 PM
#1
STL Style function parameters?
Hi,
I really like how the STL allows you to toss in a struct with a certain function present and it will use it like a function pointer (i.e. the various operators for sorting routines etc).
I'd like to use something similar myself, but the code is rather convoluted and I wasn't able to figure out how they are doing it so that I don't actually have to pass the type as a template parameter.
Does anyone know the trick they use that allows it? Is it really just looking for a function pointer or is there some sort of magic template trick that is letting that happen. If I try to use templates, I have to declare the correct type ahead of time, which doesn't work for what I want to do with it (I want that function object to be used only for that one function, and it needs to maintain some state).
-
July 28th, 2009, 12:14 PM
#2
Re: STL Style function parameters?
Originally Posted by e_torstenson
Does anyone know the trick they use that allows it? Is it really just looking for a function pointer or is there some sort of magic template trick that is letting that happen. If I try to use templates, I have to declare the correct type ahead of time, which doesn't work for what I want to do with it (I want that function object to be used only for that one function, and it needs to maintain some state).
The function template simply uses the object passed as if it were a function. If a function pointer is passed, then well and good. If a function object is passed, then operator() is overloaded, and it is also well and good. The template argument can be deduced from the type of the argument, whether function pointer or function object.
-
July 28th, 2009, 12:35 PM
#3
Re: STL Style function parameters?
Is my last post on this thread the kind of information you're looking for?
http://www.codeguru.com/forum/showthread.php?t=481203
If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).
-
July 28th, 2009, 01:01 PM
#4
Re: STL Style function parameters?
Very cool! Your solution is probably the same as the one I came up with, just a little different in terms of usage syntax:
Code:
#include <iostream>
using namespace std;
struct function {
ostream &os;
function(ostream& os) : os(os) { }
void operator()(int a) { os<<a<<"\n"; }
};
class magic {
public:
int num;
magic(int num) : num(num) { }
template<class F>
void Run(F fn) {
for (int i=0; i<num; i++) {
fn(i);
}
}
};
int main() {
magic m(20);
m.Run(function(cerr));
m.Run(function(cout));
}
For this trivial example, it works fine, and allows me to skip having to use template parameters at the calling end, which is a goal, since it makes it a bit more readable. Thanks to laserlight for clarifying the objective with STL...I've spent the time thinking of the typing at the class level, and not at the function level.
PS I'm a little embarassed that I didn't see this post in my search though Hopefully, it's OK to have two similar threads.
-
July 28th, 2009, 01:26 PM
#5
Re: STL Style function parameters?
Actually, I have a related question. If I want to create a "task queue", where each task is a functor, there is a difficulty: Each functor must be of the same type in order to fit in an STL container, and the type must be recovered entirely before it can be run if you used something generic.
Is there a typical solution to this dilemma? I know boost::variant addresses it to some degree, but that still only gives you a limited number of types to work with.
-
July 28th, 2009, 01:28 PM
#6
Re: STL Style function parameters?
An inheritance hierarchy (e.g., a Task abstract base class) with polymorphism sounds like a reasonable solution.
-
July 28th, 2009, 01:38 PM
#7
Re: STL Style function parameters?
That's the obvious one, yes. I was just hoping to avoid that if I could. I'd like an interface comparable to boost::thread, which has no such limitation of course. Plus, functors should typically be copyable, and there's problems making that assumption when using inheritance.....
Last edited by Lindley; July 28th, 2009 at 01:46 PM.
-
July 28th, 2009, 02:05 PM
#8
Re: STL Style function parameters?
If you can use Boost, boost::function might work.
The example at http://www.boost.org/doc/libs/1_39_0...html#id1849073 looks like it might apply. You could have a queue of boost::functions. This assumes that they all have the same parameters, of course...which might not be the case.
-
July 28th, 2009, 02:12 PM
#9
Re: STL Style function parameters?
That may be exactly what I want, thanks.
-
July 28th, 2009, 02:18 PM
#10
Re: STL Style function parameters?
It depends on what you really mean by "comparable to boost::thread" - or more specifically, what "comparable" means.
A boost::function object becomes a type.
You can't create a container, for example, like:
list<boost::function *>;
You must supply template parameters, which then limits you to whatever target object and function signature you've supplied.
If you want want is a very generic container of functions to be called, such that entries in the container could perform a call to any object, and any member function signature, you'll have to wrap a generic object around the boost::function which itself is a non-template base with a virtual "callback" function.
The good news, though, is that you can fashion the object representing the queue such that it's something like the boost::thread. My own operates this way:
Code:
QueProcessor q;
AnyObject o;
int p1 = 5;
double p2 = 6.25;
q.Call( o, &AnyObject::somefunc, p1, p2 );
..or many permutations like that.
Internally, however, the queue container owned by QueProcessor must be based upon a virtual "callback" to perform the call.
If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).
-
July 28th, 2009, 02:22 PM
#11
Re: STL Style function parameters?
There's only going to be one possible function signature----returning void with no arguments. So long as boost::function narrows all possible types with this signature down to a single type, it'll do. If that's not what it does, I may still have trouble....
-
July 28th, 2009, 02:25 PM
#12
Re: STL Style function parameters?
That's true. If there's only one target class and a single function signature, then you do have a single type no matter what the actual function is, and a container of them is possible.
That's also true of a simple functor, too, representing a member function call (in case you'd like to avoid boost for some reason)
If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).
-
July 28th, 2009, 02:28 PM
#13
Re: STL Style function parameters?
Let std::mem_fun? Nah, avoiding Boost isn't worth the hassle of dealing with those methods. By far the least intuitive part of the STL....
EDIT: A mem_fun_t needs to have the class type as one of its template parameters anyway, so it's no good for my purpose. Does boost::function have any such hidden template parameter?
Last edited by Lindley; July 28th, 2009 at 02:31 PM.
-
July 28th, 2009, 02:38 PM
#14
Re: STL Style function parameters?
I think boost::function will work for what you need. It's actually what boost::thread uses, which is why I suggested it:P
To be sure, I would write a short cpp file to test it, though. Then, you could catch any surprises before you make changes to real code which later have to be undone.
-
July 28th, 2009, 02:41 PM
#15
Re: STL Style function parameters?
I was thinking of something simple like this when I said "simple functor"....
Though boost::functions is applicable...
Code:
template <typename obj>
class adapter
{
private:
obj *callee;
void ( *fptr )();
public:
explicit adapter( obj &c, void ( *f ) () ) : callee( &c), fptr( f ) {}
void operator()()
{
(callee->*fptr)();
}
};
template<typename obj>
adapter<obj>
make_adapter( obj &o, void (obj::*f)() )
{
return adapter<obj>( o );
}
Usage is something like:
Code:
list<adapter<SomeObject> > flist;
.....
SomeObject myo;
flist.push_back( make_adapter( myo, &SomeObject::func ) );
Or, the class owning the queue would likely have a function "like" make_adapter which performed the submission, like:
Que<SomeObject> q;
q.Call( myo, &SomeObject::func );
Or if there's always only the same myo, perhaps its....
Que<SomeObject> q( myo );
q.Call( &SomeObject::fund );
Where myo is always the same instance for q.
Notice the use of the make_adapter function.
The issue is that any such template object is going to need parameters (objects can't deduce the parameters), but template functions can...hence the make_adapter to simplify application code interface.
Last edited by JVene; July 28th, 2009 at 02:43 PM.
If my post was interesting or helpful, perhaps you would consider clicking the 'rate this post' to let me know (middle icon of the group in the upper right of the post).
Tags for this Thread
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|