How to cast "void (MyClass::*)(int)" to "void (*)(int)"? - c++

I've looking for how to cast class member to C-style callback.
Recentrly i found answer with special bind hack allows to bind class members to C-style callbacks:
https://stackoverflow.com/a/39524069/5405443
I have this working code to bind function MyClass::f to C function f:
But i want to avoid explicit passing cb_type as template parameter to c_bind function.
In provided example CB has type void (*)(int) and Func template parameter has void (MyClass::*)(int) type.
template<typename CB, typename Func, typename... Params>
CB* c_bind(std::_Bind<Func(Params...)> function) {
return Callback<typename ActualType<CB>::type, __COUNTER__, Func>::getCallback(function);
}
typedef void (cb_type)(int);
class MyClass {
public:
void f(int x) {
std::cout << "Hello from MyClass::f(int), value: " << x << std::endl;
}
};
int main() {
MyClass mc;
auto f = c_bind<cb_type>(std::bind(&MyClass::f, mc, std::placeholders::_1));
// ^ how to avoid explicit callback type declaration here?
f(10);
return 0;
}
Also i found this piece of code (https://gist.github.com/vikchopde/73b62314379f733e8938f11b246df49c) for "unwrapping" some kind of functions.
bool ok = fu::is_unwrappable<decltype(&MyClass::f)>::value; // always false
// fu::unwrap_function<decltype(&MyClass::f)>::type::function_ptr blah; // won't compile
but it won't work by unknown to me reason.
My question is there any workaround to extract return type and args list from type with class-memeber pointer like void (MyClass::*)(int) and contruct C-like type void (*)(int) ?
Thank you for any help!

Well, in C++17, you are allowed to pass an arbitrary non-type parameter to a class with template<auto>. Therefore, we could store MyClass::f as a template parameter and parse its type with decltype. After passing this type to another templated class, we are able to extract desired types using template specialization.
The code below shows how to construct a C-style function wrapper<>::func_type.
Since you seem to bind an object to its member function, I additionally write the demo code to do this by invoking wrapper<>::bind. Hope it helps.
class MyClass {
public:
void f(int x) {
std::cout << "Hello from MyClass::f(int), value: " << x << std::endl;
}
};
void f(int x) {
std::cout << "Hello from f(int), value: " << x << std::endl;
}
template<auto F>
struct wrapper
{
template<typename> struct inner;
template<class Cls, typename Ret, typename... Args>
struct inner<Ret(Cls::*)(Args...)>
{
using func_type = Ret(Args...);
static auto bind(Cls *obj)
{
return [=](Args ...args){
return (obj->*F)(std::forward<Args>(args)...);
};
}
};
using func_type = typename inner<decltype(F)>::func_type;
static const constexpr auto bind = inner<decltype(F)>::bind;
};
int main() {
MyClass mc;
auto h = wrapper<&MyClass::f>::bind(&mc);
h(10);
using func_t = typename wrapper<&MyClass::f>::func_type;
std::function<func_t> g = f;
g(1);
return 0;
}

First of all i would like to thank #Dappur for nice example. Using your guide i will rewrite my ugly bind interface with std::_Bind usage later. Also i want to thank #Sam Varshavchik for mentioning that set of C++ books. I'll start reading it to become C++ grandmaster like you to learn how "why i cannot cast it like this". But unfortunately with my poor c++ experience I can still do it now. Here is working code:
template<class T, unsigned int n, class CallerType>
struct CallbackWrapper;
template<class Ret, class... Params, unsigned int n, class CallerType>
struct CallbackWrapper<Ret(Params...), n, CallerType> {
static auto get(std::function<Ret(Params...)>&& fn) -> Ret(*)(Params...) {
func = fn;
return static_cast<Ret(*)(Params...)>(CallbackWrapper<Ret(Params...), n, CallerType>::callback);
}
private:
static std::function<Ret(Params...)> func;
static Ret callback(Params... args) {
return func(args...);
}
};
template<class Ret, class... Params, unsigned int n, class CallerType>
std::function<Ret(Params...)> CallbackWrapper<Ret(Params...), n, CallerType>::func;
template<typename T>
struct lambda_to_stdf {
using type = void;
};
template<typename Ret, typename Class, typename... Args>
struct lambda_to_stdf<Ret(Class::*)(Args...) const> {
using type = std::function<Ret(Args...)>;
};
template<class Ret, class Cls, class... Args1, class... Args2>
auto c_bind(std::_Bind<Ret(Cls::*(Cls, Args1...))(Args2...)> function) -> Ret(*)(Args2...) {
return CallbackWrapper<Ret(Args2...), __COUNTER__, Ret(Cls::*(Cls, Args1...))(Args2...)>::get(std::move(function));
}
template<class Ret, class... Args>
auto c_bind(std::function<Ret(Args...)> function) -> Ret(*)(Args...) {
return CallbackWrapper<Ret(Args...), __COUNTER__, std::function<Ret(Args...)>>::get(std::move(function));
}
template<class F>
auto c_bind(F function) -> decltype(c_bind((typename lambda_to_stdf<decltype(&F::operator())>::type)(function))) {
return c_bind((typename lambda_to_stdf<decltype(&F::operator())>::type)(function));
}
Usage:
class MyClass {
public:
void f(int x) {
std::cout << "Hello from MyClass::f(int), value: " << x << std::endl;
}
};
int main() {
MyClass mc;
auto f = c_bind(std::bind(&MyClass::f, mc, std::placeholders::_1));
f(10);
std::function<void(int)> stdf = [](int v) {
std::cout << "hello from std::function, value: " << v << std::endl;
};
auto f2 = c_bind(stdf);
f2(100);
auto f3 = c_bind([](int v) -> int {
std::cout << "hello from lambda, value: " << v << std::endl;
return 5.0f;
});
f3(1000);
return 0;
}
Hope it will be helpful for someone.

Related

Generating lambda from class template

I have a class that registers callback functions and calls them later that looks like this.
template<typename ReturnType, typename... Args>
class Signal {
std::vector<std::function<ReturnType(Args...)>> function;
public:
template<typename... Args2>
ReturnType operator()(Args2&&... args2) {
ReturnType ret;
for (auto& func : function)
ret = func(std::forward<Args2>(args2)...);
return ret;
}
template<typename Func>
void func(Func const &func) {
function.push_back(std::function<ReturnType(Args...)>(func));
}
template<typename Class, typename Instance>
void mfunc(ReturnType(Class::*func)(Args...), Instance &instance) {
mfunc2(func, instance, make_int_sequence<sizeof...(Args)>{});
}
template<typename Class, typename Instance, int... I>
void mfunc2(ReturnType(Class::*func)(Args...), Instance &instance, int_sequence<I...>) {
using namespace std::placeholders;
function.push_back(std::function<ReturnType(Args...)>(std::bind(func, &instance, placeholder_template<I>{}...)));
}
};
#include <iostream>
class foo {
public:
int bar(int x, double y) {
std::cout << x << " and " << y << std::endl;
return x*2;
}
};
int main() {
foo foo1;
Signal<int, int, double> sig;
sig.mfunc(&foo::bar, foo1);
std::cout << "Return: " << sig(5,5.5) << std::endl;
}
I heard a talk from Stephan T. Lavavej today, and one of the things he was saying is that std::bind should be avoided and use lambdas instead. So to learn something new I figured I would try and change the std::bind call in mfunc2 to a lambda, but I'm quite new to templates and can't figure out how to generate the code I want.
The current placeholder_template with make_int_sequence I found here on SO, but I can't really wrap my head around how exactly it works, or where to find any good reading on it...
Args... holds the argument types that should be accepted by the lambda, but I need to somehow create variable names such as var1, var2, var3 ect depending on the sizeof...(Args) and then merge them together.
So for example < int, int, int >, Args... would hold int, int.
I then want to construct the lambda as
[func, &instance](int var1, int var2) -> ReturnType { return func(&instance, var1, var2); }
How could I accomplish this?
This should do the job:
template<typename ReturnType, typename... Args>
class Signal {
std::vector<std::function<ReturnType(Args...)>> function;
public:
template<typename... Args2>
ReturnType operator()(Args2&&... args2) {
ReturnType ret;
for (auto& func : function)
ret = func(std::forward<Args2>(args2)...);
return ret;
}
template<typename Func>
void func(Func const &func) {
function.push_back(std::function<ReturnType(Args...)>(func));
}
template<typename Class, typename Instance>
void mfunc(ReturnType(Class::*func)(Args...), Instance& instance) {
function.push_back([&instance, func](Args&&... args) {
return (instance.*func)(std::forward<Args>(args)...);
});
}
};
https://ideone.com/gjPdWN
Note that in your operator(), you basically throw away all return values except the last one. Is that behaviour intended?

Compile-time switch for mutable/immutable lambda

I am writing a class member function that will take a lambda with a given type T in the function argument. My question is: is it possible to overload the member function at compile-time based on the mutability of the argument? Below is the example:
// T is a given type for class.
template <typename T>
class Wrapper {
T _t;
// For T&
template <typename F, typename R = std::result_of_t<F(T&)>>
std::enable_if_t<std::is_same<R, void>::value> operator()(F&& f) {
f(_t);
}
// For const T&
template <typename F, typename R = std::result_of_t<F(const T&)>>
std::enable_if_t<std::is_same<R, void>::value> operator()(F&& f) const {
f(_t);
}
};
So, what I want is, if the give lambda is with the following signature, the first operator should be invoked.
[](T&) {
...
};
For constant argument, the second should be invoked.
[](const T&) {
}
If you plan to use non-capturing lambdas only, you can rely on the fact that they decay to pointers to functions.
It follows a minimal, working example:
#include<type_traits>
#include<iostream>
template <typename T>
class Wrapper {
T _t;
public:
auto operator()(void(*f)(T &)) {
std::cout << "T &" << std::endl;
return f(_t);
}
auto operator()(void(*f)(const T &)) const {
std::cout << "const T &" << std::endl;
return f(_t);
}
};
int main() {
Wrapper<int> w;
w([](int &){});
w([](const int &){});
}
Otherwise you can use two overloaded functions as it follows:
#include<type_traits>
#include<iostream>
#include<utility>
template <typename T>
class Wrapper {
T _t;
template<typename F>
auto operator()(int, F &&f)
-> decltype(std::forward<F>(f)(const_cast<const T &>(_t))) const {
std::cout << "const T &" << std::endl;
return std::forward<F>(f)(_t);
}
template<typename F>
auto operator()(char, F &&f) {
std::cout << "T &" << std::endl;
return std::forward<F>(f)(_t);
}
public:
template<typename F>
auto operator()(F &&f) {
return (*this)(0, std::forward<F>(f));
}
};
int main() {
Wrapper<int> w;
w([](int &){});
w([](const int &){});
}

C++ function call wrapper with function as template argument

I'm trying to create a generic wrapper function that takes a function as a template argument and takes the same arguments as that function as its arguments. For example:
template <typename F, F func>
/* return type of F */ wrapper(Ts... Args /* not sure how to get Ts*/)
{
// do stuff
auto ret = F(std::forward<Ts>(args)...);
// do some other stuff
return ret;
}
The solution needs to be castable to a function pointer with the same type as func so that I can pass it to a C api. In other words, the solution needs to be a function and not a function object. Most importantly, I need to be able to do work in the wrapper function.
If the inline comments aren't clear, I'd like to be able to do something like the following:
struct c_api_interface {
int (*func_a)(int, int);
int (*func_b)(char, char, char);
};
int foo(int a, int b)
{
return a + b;
}
int bar(char a, char b, char c)
{
return a + b * c;
}
c_api_interface my_interface;
my_interface.func_a = wrapper<foo>;
my_interface.func_b = wrapper<bar>;
I looked for related posts and found these, but none of them are quite what I'm trying to do. Most of these posts concern function objects. Is what I'm trying to do even possible?
Function passed as template argument
Function wrapper via (function object) class (variadic) template
How does wrapping a function pointer and function object work in generic code?
How do I get the argument types of a function pointer in a variadic template class?
Generic functor for functions with any argument list
C++ Functors - and their uses
In response to the first 2 responses, I edited the question to make it clear that I need to be able to do work in the wrapper function (i.e. modify some global state before and after the call to the wrapped function)
template<class F, F f> struct wrapper_impl;
template<class R, class... Args, R(*f)(Args...)>
struct wrapper_impl<R(*)(Args...), f> {
static R wrap(Args... args) {
// stuff
return f(args...);
}
};
template<class F, F f>
constexpr auto wrapper = wrapper_impl<F, f>::wrap;
Use as wrapper<decltype(&foo), foo>.
#include <utility>
#include <iostream>
struct c_api_interface { int (*func_a)(int, int); int (*func_b)(char, char, char); };
int foo(int a, int b) { return a + b; }
int bar(char a, char b, char c) { return a + b * c; }
template<typename Fn, Fn fn, typename... Args>
typename std::result_of<Fn(Args...)>::type
wrapper(Args... args) {
std::cout << "and ....it's a wrap ";
return fn(std::forward<Args>(args)...);
}
#define WRAPIT(FUNC) wrapper<decltype(&FUNC), &FUNC>
int main() {
c_api_interface my_interface;
my_interface.func_a = WRAPIT(foo);
my_interface.func_b = WRAPIT(bar);
std:: cout << my_interface.func_a(1,1) << std::endl;
std:: cout << my_interface.func_b('a','b', 1) << std::endl;
return 0;
}
see http://rextester.com/ZZD18334
you may try something like that (Ugly, but works)
#include <iostream>
#include <functional>
struct wrapper_ctx
{
wrapper_ctx ()
{
std::cout << "Before" << std::endl;
}
~wrapper_ctx ()
{
std::cout << "after" << std::endl;
}
};
template <typename F, typename... Args>
auto executor (F&& f, Args&&... args) -> typename std::result_of<F(Args...)>::type
{
wrapper_ctx ctx;
return std::forward<F>(f)( std::forward<Args>(args)...);
}
template <typename F>
class wrapper_helper;
template<typename Ret, typename... Args>
class wrapper_helper <std::function<Ret(Args...)>>
{
std::function<Ret(Args...)> m_f;
public:
wrapper_helper( std::function<Ret(Args...)> f )
: m_f(f) {}
Ret operator()(Args... args) const
{
return executor (m_f, args...);
}
};
template <typename T>
wrapper_helper<T> wrapper (T f)
{
return wrapper_helper <T>(f);
}
int sum(int x, int y)
{
return x + y;
}
int main (int argc, char* argv [])
{
std::function<int(int, int)> f = sum;
auto w = wrapper (f);
std::cout << "Executing the wrapper" << std::endl;
int z = w(3, 4);
std::cout << "z = " << z << std::endl;
}
you probably need something like
template <typename F>
class Wrapper {
public:
Wrapper(F *func) : function(func) {}
operator F* () { return function; }
F *function;
};
Which you can use like void (*funcPtr)(int) = Wrapper<void(int)>(&someFunction);
I think that will be the concise way to do what you want:
template <typename F>
F* wrapper(F* pFunc)
{
return pFunc;
}
and use it like this:
my_interface.func_a = wrapper(foo);
my_interface.func_a(1, 3);
You may try this
template <class R, class... Args>
struct wrap
{
using funct_type = R(*)(Args...);
funct_type func;
wrap(funct_type f): func(f) {};
R operator()(Args&&... args)
{
//before code block
std::cout << "before calling\n";
R ret=func(std::forward<Args>(args)...);
//after code block
std::cout << "After calling\n";
}
};
use like this for example:
int somefunc(double &f, int x);
auto wrapped_somefunc=wrap{somefunc};
double f=1.0;
int x = 2;
auto result=wrapped_somefunc(f,x);
This one is for c++17 and newer uses auto template parameters:
template <auto func, class... Args>
auto wrap_func(Args... args)
{
std::cout << "before calling wrapped func\n";
auto ret = func(args...);
std::cout << "after calling wrapped func\n";
return ret;
}
use for example:
int some_func(int a, int b);
auto ret = wrap_func<some_func>(2, 3);

Passing member function with all arguments to std::function

How can I create a std::function from member function without need for typing std::placeholders::_1, std::placeholders::_2, etc - I would like to "placehold" all arguments, saving only the object itself.
struct Foo{
int bar(int,float,bool) {return 0;}
};
int baz(int,float,bool) {return 0;}
int main() {
Foo object;
std::function<int(int,float,bool)> fun1 = baz; // OK
std::function<int(int,float,bool)> fun2 = std::bind(&Foo::bar, object); // WRONG, needs placeholders
}
I don't want to provide arguments at this stage, I just want to store function + object somewhere. For example I would like to have std::vector with both global functions and member functions. It was easy to do with FastDelegate (fastdelegate::MakeDelegate(object, &Class::function)).
I don't want to use lambda as it would require me to retype arguments as well. I just want old FastDelegate behaviour.
You can use function template which will deduce all member function parameter types, like this:
template<typename Obj, typename Result, typename ...Args>
auto make_delegate(const Obj &x, Result (Obj::*fun)(Args...)) -> // ...
And will return special delegate object, which will contain your object (or pointer to it) and just forward all passed arguments to member function of underlying object:
template<typename Obj, typename Result, typename ...Args>
struct Delegate
{
Obj x;
Result (Obj::*f)(Args...);
template<typename ...Ts>
Result operator()(Ts&&... args)
{
return (x.*f)(forward<Ts>(args)...);
}
};
You will get following usage syntax:
function<int(int,float,bool)> fun = make_delegate(object, &Foo::bar);
Here is full example:
#include <functional>
#include <iostream>
#include <utility>
using namespace std;
struct Foo
{
int bar(int x, float y, bool z)
{
cout << "bar: " << x << " " << y << " " << z << endl;
return 0;
}
};
int baz(int x, float y, bool z)
{
cout << "baz: " << x << " " << y << " " << z << endl;
return 0;
}
template<typename Obj, typename Result, typename ...Args>
struct Delegate
{
Obj x;
Result (Obj::*f)(Args...);
template<typename ...Ts>
Result operator()(Ts&&... args)
{
return (x.*f)(forward<Ts>(args)...);
}
};
template<typename Obj, typename Result, typename ...Args>
auto make_delegate(const Obj &x, Result (Obj::*fun)(Args...))
-> Delegate<Obj, Result, Args...>
{
Delegate<Obj, Result, Args...> result{x, fun};
return result;
}
int main()
{
Foo object;
function<int(int,float,bool)> fun[] =
{
baz,
make_delegate(object, &Foo::bar) // <---- usage
};
for(auto &x : fun)
x(1, 1.0, 1);
}
Output is:
baz: 1 1 1
bar: 1 1 1
Live Demo on Coliru
If you don't want to use placeholders, then std::bind is not for you:
Use lambda:
Foo object;
std::function<int(int,float,bool)> fun = [&object](int a, float b, bool c) {
return object.bar(a,b,c);
};
You can capture object by value if you wish. Perhaps you realize this is no better than using placeholders, as you're typing parameters anyway — in fact you type more in this case!
You can easily do this with variadic generic lambdas in C++14:
template<typename F, typename C>
auto smart_bind(F f, C* c)
{
return [c, f](auto&&... args) { return (c->*f)(std::forward<decltype(args)>(args)...); };
}
// In your code:
std::function<int(int,float,bool)> fun2 = smart_bind(&Foo::bar, &object);
Live demo: https://ideone.com/deR4fy

c++0x: overloading on lambda arity

I'm trying to create a function which can be called with a lambda that takes either 0, 1 or 2 arguments. Since I need the code to work on both g++ 4.5 and vs2010(which doesn't support variadic templates or lambda conversions to function pointers) the only idea I've come up with is to choose which implementation to call based on arity. The below is my non working guess at how this should look. Is there any way to fix my code or is there a better way to do this in general?
#include <iostream>
#include <functional>
using namespace std;
template <class Func> struct arity;
template <class Func>
struct arity<Func()>{ static const int val = 0; };
template <class Func, class Arg1>
struct arity<Func(Arg1)>{ static const int val = 1; };
template <class Func, class Arg1, class Arg2>
struct arity<Func(Arg1,Arg2)>{ static const int val = 2; };
template<class F>
void bar(F f)
{
cout << arity<F>::val << endl;
}
int main()
{
bar([]{cout << "test" << endl;});
}
A lambda function is a class type with a single function call operator. You can thus detect the arity of that function call operator by taking its address and using overload resolution to select which function to call:
#include <iostream>
template<typename F,typename R>
void do_stuff(F& f,R (F::*mf)() const)
{
(f.*mf)();
}
template<typename F,typename R,typename A1>
void do_stuff(F& f,R (F::*mf)(A1) const)
{
(f.*mf)(99);
}
template<typename F,typename R,typename A1,typename A2>
void do_stuff(F& f,R (F::*mf)(A1,A2) const)
{
(f.*mf)(42,123);
}
template<typename F>
void do_stuff(F f)
{
do_stuff(f,&F::operator());
}
int main()
{
do_stuff([]{std::cout<<"no args"<<std::endl;});
do_stuff([](int a1){std::cout<<"1 args="<<a1<<std::endl;});
do_stuff([](int a1,int a2){std::cout<<"2 args="<<a1<<","<<a2<<std::endl;});
}
Be careful though: this won't work with function types, or class types that have more than one function call operator, or non-const function call operators.
I thought the following would work but it doesn't, I'm posting it for two reasons.
To save people the time if they had the same idea
If someone knows why this doesn't work, I'm not 100% sure I understand (although I have my suspicions)
Code follows:
#include <iostream>
#include <functional>
template <typename Ret>
unsigned arity(std::function<Ret()>) { return 0; }
template <typename Ret, typename A1>
unsigned arity(std::function<Ret(A1)>) { return 1; }
template <typename Ret, typename A1, typename A2>
unsigned arity(std::function<Ret(A1, A2)>) { return 2; }
// rinse and repeat
int main()
{
std::function<void(int)> f = [](int i) { }; // this binds fine
// Error: no matching function for call to 'arity(main()::<lambda(int)>)'
std::cout << arity([](int i) { });
}
Compile time means of obtaining the arity of a function or a function object, including that of a lambda:
int main (int argc, char ** argv) {
auto f0 = []() {};
auto f1 = [](int) {};
auto f2 = [](int, void *) {};
std::cout << Arity<decltype(f0)>::value << std::endl; // 0
std::cout << Arity<decltype(f1)>::value << std::endl; // 1
std::cout << Arity<decltype(f2)>::value << std::endl; // 2
std::cout << Arity<decltype(main)>::value << std::endl; // 2
}
template <typename Func>
class Arity {
private:
struct Any {
template <typename T>
operator T ();
};
template <typename T>
struct Id {
typedef T type;
};
template <size_t N>
struct Size {
enum { value = N };
};
template <typename F>
static Size<0> match (
F f,
decltype(f()) * = nullptr);
template <typename F>
static Size<1> match (
F f,
decltype(f(Any())) * = nullptr,
decltype(f(Any())) * = nullptr);
template <typename F>
static Size<2> match (
F f,
decltype(f(Any(), Any())) * = nullptr,
decltype(f(Any(), Any())) * = nullptr,
decltype(f(Any(), Any())) * = nullptr);
public:
enum { value = Id<decltype(match(static_cast<Func>(Any())))>::type::value };
};
This way works:
template<typename F>
auto call(F f) -> decltype(f(1))
{
return f(1);
}
template<typename F>
auto call(F f, void * fake = 0) -> decltype(f(2,3))
{
return f(2,3);
}
template<typename F>
auto call(F f, void * fake = 0, void * fake2 = 0) -> decltype(f(4,5,6))
{
return f(4,5,6);
}
int main()
{
auto x1 = call([](int a){ return a*10; });
auto x2 = call([](int a, int b){ return a*b; });
auto x3 = call([](int a, int b, int c){ return a*b*c; });
// x1 == 1*10
// x2 == 2*3
// x3 == 4*5*6
}
It works for all callable types (lambdas, functors, etc)