Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function which converts from from a_func(A a_in) to b_func(B b_in) (c++)

I have a class of function (call it AFunc) which takes a parameter of type A, and a class of function (call it BFunc) which takes a parallel parameter of type B (i.e. there is a straightforward conversion from objects of type A to those of type B).

I need to write a function like the following:

using Afunc = AReturnType(*)(A);

using BFunc = BReturnType(*)(B);

BFunc convertFunction(AFunc a_func_in)
{
    BReturnType(*b_func_out) =
        [&](B b_in) {
            A a_in = A(b_in);
            AReturnType a_out = a_func_in(a_in);
            return BReturnType(a_out);
    };
    return b_func_out;
}

That is, a function which takes a function compatible with A types and returns a function compatible with B types.

My first thought was to define a function within the conversion function, but I quickly discovered that local functions are not supported in c++. My next thought was to use a lambda expression as above, but I have since learned that lambda functions can only be decayed to function pointers if they don't capture any references, however in this case the lambda needs to be aware of the AFunc parameter provided to the wider conversion function.

This is where I've run out of ideas. Is there any other way of doing this?

like image 472
Cam Avatar asked Dec 05 '25 10:12

Cam


1 Answers

The problem is that having a function pointer is stronger than simply having a callable object. The latter could be a function pointer, but it could also be a closure or a functor, both of which carry state. A function pointer is just that: a pointer to a function. No state, no special tricks. Just one chunk of code that can be executed on demand.

So, at least, there's no way to pass an AFunc at runtime and get a BFunc, the way you've defined everything, because that would involve generating new functions in the code itself at runtime, which C++ doesn't allow.

However, if you know the AFunc you want to apply this too at compile-time, we can use templates to get the same result. A template is evaluated at compile-time and actually generates code, so we can use it to come up with functions which have genuine function pointers. In fact, we're not even going to write a conversion function; we're just going to write our BFunc and then template parameterize it.

template <AFunc f>
BReturnType bFunc(B b) {
  return f(b);
}

Assuming the appropriate conversions exist, you can write something like BFunc b = bFunc<sampleAFunc>; and the compiler will generate the appropriate function (and corresponding pointer) for you.

like image 64
Silvio Mayolo Avatar answered Dec 07 '25 00:12

Silvio Mayolo