Reputation: 2968
I'm trying to figure out how to write this function:
template <typename Bound>
Bound::result_type callFromAnyList(Bound b, list<any> p)
{
}
Then, if I had some function:
double myFunc(string s, int i)
{
return -3.0;
}
I could call it by doing something like this:
list<any> p;
p.push_back((string)"Hello");
p.push_back(7);
double result = callFromAnyList(bind(myFunc, _1, _2), p);
Is it possible to write something like my callFromAnyList
function? Can you inspect the result type and the parameter types from the type returned from bind
? And then call any_cast<P1>(*p.begin())
, etc? I've tried to understand the bind code, but it's a little hard to follow, and it doesn't appear as though they wrote it with inspection in mind.
Upvotes: 1
Views: 799
Reputation: 2968
I ended up doing this for now -
void invoke(void (f)(), list<any>& params)
{
f();
}
template <typename R>
void invoke(R (f)(), list<any>& params)
{
params.push_front(f());
}
template <typename T0>
void invoke(void (f)(T0), list<any>& params)
{
T0 t0 = any_cast<T0>(*params.begin()); params.pop_front();
f(t0);
}
template <typename R, typename T0>
void invoke(R (f)(T0), list<any>& params)
{
T0 t0 = any_cast<T0>(*params.begin()); params.pop_front();
params.push_front(f(t0));
}
template <typename T0, typename T1>
void invoke(void (f)(T0, T1), list<any>& params)
{
T0 t0 = any_cast<T0>(*params.begin()); params.pop_front();
T1 t1 = any_cast<T1>(*params.begin()); params.pop_front();
f(t0, t1);
}
template <typename R, typename T0, typename T1>
void invoke(R (f)(T0, T1), list<any>& params)
{
T0 t0 = any_cast<T0>(*params.begin()); params.pop_front();
T1 t1 = any_cast<T1>(*params.begin()); params.pop_front();
params.push_front(f(t0, t1));
}
template <typename T0, typename T1, typename T2>
void invoke(void (f)(T0, T1, T2), list<any>& params)
{
T0 t0 = any_cast<T0>(*params.begin()); params.pop_front();
T1 t1 = any_cast<T1>(*params.begin()); params.pop_front();
T2 t2 = any_cast<T2>(*params.begin()); params.pop_front();
f(t0, t1, t2);
}
template <typename R, typename T0, typename T1, typename T2>
void invoke(R (f)(T0, T1, T2), list<any>& params)
{
T0 t0 = any_cast<T0>(*params.begin()); params.pop_front();
T1 t1 = any_cast<T1>(*params.begin()); params.pop_front();
T2 t2 = any_cast<T2>(*params.begin()); params.pop_front();
params.push_front(f(t0, t1, t2));
}
I'm lacking the full power of boost::bind - like, I can't handle method pointers - but I also realized that by doing this, I've got a stack processor. I can keep invoking methods that operator on the parameters on the stack.
Upvotes: 0
Reputation: 507273
As you updated your concerns in the comment sections, here the answer. Just getting the return type of a function is possible:
template<typename>
struct return_of;
template<typename R>
struct return_of<R(*)()> {
typedef R type;
};
template<typename R, typename P1>
struct return_of<R(*)(P1)> {
typedef R type;
typedef P1 parameter_1;
};
void foo(int);
template<typename Func>
typename return_of<Func>::parameter_1 bar(Func f) {
return 42;
}
// call: bar(foo);
I guess you see what this comes down to :) You can use boost function types which already has solved it: http://www.boost.org/doc/libs/1_37_0/libs/function_types/doc/html/index.html
Upvotes: 1