So I sort of tried to accomplish “the impossible” at least in C++20 and with the constraint that the class for which I am extracting a member function pointer can be evaluated as a constexpr.
#include <iostream>
struct AddFunctor
{
double val;
double operator()(double x) const { return val + x; }
};
struct SubFunctor
{
double val;
double operator()(double x) const { return val - x; }
};
typedef double(*DblFn)(double); // C-style type of above operator()
// the below is doable only in C++20 which is more liberal about NTTP-s
template<typename FunctorType, FunctorType functor>
double functorWrapper(double x) { return functor(x); }
// below wrapper doesn't work, see below
template<typename FunctorType>
DblFn makeWrapper(FunctorType fr) { return &(functorWrapper<FunctorType, fr>); }
int main()
{
DblFn fp;
// if constexpr below is changed to const, one gets:
// error: assigning to 'DblFn' (aka 'double (*)(double)') from incompatible type '<overloaded function type>'
constexpr AddFunctor af{2};
constexpr SubFunctor sf{3};
// fp = &(af.operator()); // error: cannot create a non-constant pointer to member function
fp = &(functorWrapper<AddFunctor, af>);
std::cout << fp(6.283) << std::endl;
fp = &(functorWrapper<SubFunctor, sf>);
std::cout << fp(6.283) << std::endl;
// if the below "if 0" block is uncommented, one gets:
/*
<src>:21:46: error: address of overloaded function 'functorWrapper' does not match required type 'double (double)'
DblFn makeWrapper(FunctorType fr) { return &(functorWrapper<FunctorType, fr>); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<src>:40:10: note: in instantiation of function template specialization 'makeWrapper<AddFunctor>' requested here
fp = makeWrapper(af);
^
<src>:18:8: note: candidate template ignored: invalid explicitly-specified argument for template parameter 'functor'
double functorWrapper(double x) { return functor(x); }
^
1 error generated.
*/
#if 0
fp = makeWrapper(af);
std::cout << fp(2.718) << std::endl;
#endif
}
As I am not C++-savvy enough, I ask this question: is it possible to write a makeWrapper function as I have tried to do without manually specifying the FunctorType and find it out using template argument type deduction, and if yes how?
PS: My library is implemented in C++ for it's expressive power but the interface is basically C for FFI flexibility with ifdef __cplusplus function goodies available. Hence I'm specifically looking for solutions for my C++ clients to convert to C-style pointers to maintain a common ABI.
If you can use
std::function, this is rather a simple case of wrapping theclass::operator()into a lambda function.Now you can
Live demo
The c-style function pointers require the type of the member functions to be accurate (i.e.
const, nonconst,noexceptetc.); hence the issue! On the other handstd::functionhelps you with its type erasure power to capture, the wrapper (stateful) lambda and achieve the goal.