Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wrap multiple function overloads with a generic TR1 function object?

I have a function foo() that is being provided in a library context. The library defines a handful of overloads for this function, like:

char foo(float x, int y);
short foo(double x, char y);

(I made the above argument/result types up. The takeaway is that there isn't a generic relationship between the argument types and the overload's corresponding return type.)

The idea is that the library user can add overloads for foo() for their own user-defined types as needed. Function overloading accomplishes this very easily.

I would like to make the foo() family of functions usable in a Boost.Proto expression. In order to do so, I think I would need to wrap the above in a function object with a template call operator:

struct foo_wrap
{
    template <typename A1, typename A2>
    result_type operator()(A1 a1, A2 a2) { return foo(a1, a2); }
};

The problem comes with how to define result_type. I realize this would be easy with C++11 and decltype() and trailing function return types, but I'm looking for a C++03 solution. Therefore, foo_wrap needs to be a TR1-style function object. I need to find a way to define result_type as a compile-time function of the argument types A1 and A2. This is needed not only for the return type of operator(), but also for the TR1 result_of protocol to work as well. In short:

  • Is there a metaprogramming technique that, given a function name and a set of argument types, will yield the function's corresponding return type?
  • Alternatively, is there another technique that I can use to wrap multiple overloads of a function with a generic function object?
like image 547
Jason R Avatar asked Sep 30 '22 04:09

Jason R


1 Answers

You may feed manually a traits for that:

template <typename A1, typename A2>
struct foo_wrap_result;

with

struct foo_wrap
{
    template <typename A1, typename A2>
    typename foo_wrap_result<A1, A2>::type
    operator()(A1 a1, A2 a2) const { return foo(a1, a2); }
};

And specialization of the traits:

template <>
struct foo_wrap_result<float, int> { typedef char type; };

template <>
struct foo_wrap_result<double, char> { typedef short type; };
like image 96
Jarod42 Avatar answered Oct 05 '22 08:10

Jarod42