the swine the swine - 1 month ago 4x
C++ Question

Retrieve argument type of function operator of an object

I have a wrapper which transforms functions taking several arguments into functions taking just a single argument (values for the other arguments are provided). This code works with functions:

template <class R, class F, class A0, class A1>
class CMyWrapper {
F m_f;
A0 m_default_a0;

CMyWrapper(F f, const A0 &default_a0)
:m_f(f), m_default_a0(default_a0)

R operator ()(const A1 &a1) const
return m_f(m_default_a0, a1);

template <class R, class A0, class A1>
CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1>
SupplyConstArg(R (*fun)(const A0&, const A1&), const A0 &default_a0)
return CMyWrapper<R, R (*)(const A0&, const A1&), A0, A1>(fun, default_a0);

double MyFunc(const double &x, const double &y); // some function

so now I can do e.g.
SupplyConstArg(MyFunc, 1.23)(4.56)
which calls
MyFunc(1.23, 4.56)
(the left part of this expression is a function object which supplies a constant first argument). So far so good.

However, I have some difficulties in writing a similar function working for function objects rather than functions (I'd like to avoid function pointers for performance reasons where possible). Assuming:

struct CMyFunObj {
double operator ()(const double &x, const double &y);

my problem is how do I match the return type or the types of the arguments, given an instance of such function object? So far, I came up with:

template <class F, class R, class A0, class A1>
R Infer(F f, R (F::*fun)(const A0 &a0, const A1 &a1) = &F::operator ());

which sort of works, but only if the second argument is also specified, e.g. by calling:

Infer(CMyFunObj(), &CMyFunObj::operator ());

but not if I omit the second argument and rely on the default value. Any ideas how to do it in C++03?


In C++03, you can't really infer the type like that (unless you want to use like typeof), so you have to actually provide it:

struct CMyFunObj {
    typedef double result_type;
    double operator()(const double &x, const double &y);

And now you can use that additional bit of information:

template <class F, class A0>
CMyWrapper<typename F::result_type, F, A0>
SupplyConstArg(F f, A0 const& a0) {
    return CMyWrapper<typename F::result_type, F, A0>(f, a0);

SupplyConstArg(CMyFunObj(), 4.0)(5.0);

You don't need the type A1 in CMyWrapper, that can be a template argument on its operator().