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?
Related
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.
I currently have a system to "connect" signals to functions. This signal is a variadic template that has as template parameters the arguments of the functions it can connect to.
In the current implementation, I obviously cannot connect to functions whose arguments aren't exactly the same (or those that can be converted to) as the signal's parameters. Now, as I'm trying to mimic Qt's signal/slot/connect, I'd also like to connect a signal of N parameters to a slot of M<N parameters, which is perfectly well-defined (i.e. ignore the >M parameters of the signal and just pass the first M to the connected function). For an example of the code I have in its most simplistic form, see Coliru.
So the question is two-fold:
How do I make the connect call work for a function void g(int);?
How do I make the emit call work for a function void g(int);?
I'm guessing I'll have to make some "magic" parameter pack reducer for both the slot and its call function, but I can't see how it all should fit together so it's quite hard to actually start trying to code a solution. I'm OK with a C++17-only solution, if at least Clang/GCC and Visual Studio 2015 can compile it.
The code linked above for completeness:
#include <memory>
#include <vector>
template<typename... ArgTypes>
struct slot
{
virtual ~slot() = default;
virtual void call(ArgTypes...) const = 0;
};
template<typename Callable, typename... ArgTypes>
struct callable_slot : slot<ArgTypes...>
{
callable_slot(Callable callable) : callable(callable) {}
void call(ArgTypes... args) const override { callable(args...); }
Callable callable;
};
template<typename... ArgTypes>
struct signal
{
template<typename Callable>
void connect(Callable callable)
{
slots.emplace_back(std::make_unique<callable_slot<Callable, ArgTypes...>>(callable));
}
void emit(ArgTypes... args)
{
for(const auto& slot : slots)
{
slot->call(args...);
}
}
std::vector<std::unique_ptr<slot<ArgTypes...>>> slots;
};
void f(int, char) {}
int main()
{
signal<int, char> s;
s.connect(&f);
s.emit(42, 'c');
}
template<class...> struct voider { using type = void; };
template<class... Ts> using voidify = typename voider<Ts...>::type;
template<class C, class...Args>
using const_lvalue_call_t = decltype(std::declval<const C&>()(std::declval<Args>()...));
template<class T, std::size_t...Is>
auto pick_from_tuple_impl(T &&, std::index_sequence<Is...>)
-> std::tuple<std::tuple_element_t<Is, T>...>;
template<class Tuple, class = std::enable_if_t<(std::tuple_size<Tuple>::value > 0)>>
using drop_last = decltype(pick_from_tuple_impl(std::declval<Tuple>(),
std::make_index_sequence<std::tuple_size<Tuple>::value - 1>()));
template<class C, class ArgsTuple, class = void>
struct try_call
: try_call<C, drop_last<ArgsTuple>> {};
template<class C, class...Args>
struct try_call<C, std::tuple<Args...>, voidify<const_lvalue_call_t<C, Args...>>> {
template<class... Ts>
static void call(const C& c, Args&&... args, Ts&&... /* ignored */) {
c(std::forward<Args>(args)...);
}
};
Then in callable_slot:
void call(ArgTypes... args) const override {
using caller = try_call<Callable, std::tuple<ArgTypes...>>;
caller::call(callable, std::forward<ArgTypes>(args)...);
}
For member pointer support (this requires SFINAE-friendly std::result_of), change const_lvalue_call_t to
template<class C, class...Args>
using const_lvalue_call_t = std::result_of_t<const C&(Args&&...)>;
then change the actual call in try_call::call to
std::ref(c)(std::forward<Args>(args)...);
This is poor man's std::invoke for lvalue callables. If you have C++17, just use std::invoke directly (and use std::void_t instead of voidify, though I like the sound of the latter).
Not sure to understand what do you exactly want but... with std::tuple and std::make_index_sequence ...
First of all you need a type traits that give you the number of arguments of a function (or std::function)
template <typename>
struct numArgs;
template <typename R, typename ... Args>
struct numArgs<R(*)(Args...)>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename R, typename ... Args>
struct numArgs<std::function<R(Args...)>>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
Next you have to add a constexpr value in callable_slot to memorize the number of arguments in the Callable function
static constexpr std::size_t numA { numArgs<Callable>::value };
Then you have to modify the call() method to pack the arguments in a std::tuple<ArgTypes...> and call another method passing the tuple and an index sequence from 0 to numA
void call(ArgTypes... args) const override
{ callI(std::make_tuple(args...), std::make_index_sequence<numA>{}); }
Last you have to call, in CallI(), the callable() function with only the first numA elements of the tuple of arguments
template <std::size_t ... Is>
void callI (std::tuple<ArgTypes...> const & t,
std::index_sequence<Is...> const &) const
{ callable(std::get<Is>(t)...); }
The following is a full working example
#include <memory>
#include <vector>
#include <iostream>
#include <functional>
template <typename>
struct numArgs;
template <typename R, typename ... Args>
struct numArgs<R(*)(Args...)>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename R, typename ... Args>
struct numArgs<std::function<R(Args...)>>
: std::integral_constant<std::size_t, sizeof...(Args)>
{ };
template <typename ... ArgTypes>
struct slot
{
virtual ~slot() = default;
virtual void call(ArgTypes...) const = 0;
};
template <typename Callable, typename ... ArgTypes>
struct callable_slot : slot<ArgTypes...>
{
static constexpr std::size_t numA { numArgs<Callable>::value };
callable_slot(Callable callable) : callable(callable)
{ }
template <std::size_t ... Is>
void callI (std::tuple<ArgTypes...> const & t,
std::index_sequence<Is...> const &) const
{ callable(std::get<Is>(t)...); }
void call(ArgTypes... args) const override
{ callI(std::make_tuple(args...), std::make_index_sequence<numA>{}); }
Callable callable;
};
template <typename ... ArgTypes>
struct signal
{
template <typename Callable>
void connect(Callable callable)
{
slots.emplace_back(
std::make_unique<callable_slot<Callable, ArgTypes...>>(callable));
}
void emit(ArgTypes... args)
{ for(const auto& slot : slots) slot->call(args...); }
std::vector<std::unique_ptr<slot<ArgTypes...>>> slots;
};
void f (int i, char c)
{ std::cout << "--- f(" << i << ", " << c << ")" << std::endl; }
void g (int i)
{ std::cout << "--- g(" << i << ")" << std::endl; }
struct foo
{
static void j (int i, char c)
{ std::cout << "--- j(" << i << ", " << c << ")" << std::endl; }
void k (int i)
{ std::cout << "--- k(" << i << ")" << std::endl; }
};
int main ()
{
std::function<void(int, char)> h { [](int i, char c)
{ std::cout << "--- h(" << i << ", " << c << ")" << std::endl; }
};
std::function<void(int)> i { [](int i)
{ std::cout << "--- i(" << i << ")" << std::endl; }
};
using std::placeholders::_1;
foo foo_obj{};
std::function<void(int)> k { std::bind(&foo::k, foo_obj, _1) };
signal<int, char> s;
s.connect(f);
s.connect(g);
s.connect(h);
s.connect(i);
s.connect(foo::j);
s.connect(k);
s.emit(42, 'c');
}
This example need C++14 because use std::make_index_sequence and std::index_sequence.
Substitute both of they and prepare a C++11 compliant solution isn't really difficult.
So suppose, that I have got a class, that contains functional object and in the constructor call I pass arguments, that are to be passed to the functional object some time later. Something like:
class Binder{
public:
Binder(functional_object, listOfParameters);
callFunctionalObject(); // calls functional object with given list of parameters
};
Before C++11 I could not use Variadic templates, so one would do:
struct none{};
template <typename T1, typename T2=none, typename T3=none>
class Binder{
public:
Binder(T1 functionalObject, T2 arg1=none(), T3arg3=none());
void callFunctionalObject();
private:
T1 m_functionalObject;
T2 m_arg1;
T3 m_arg2;
};
Where callFunctionalobject could be implemented as follows:
template<typename T1, typename T2, typename T3>
void Binder<T1,T2,T3>::callFunctionalObject(){
callImpl(m_functionalObject, m_arg1, m_arg2);
}
and callImpl would be overloaded to recognize objects of type none to pass proper amount of arguments to the functional object.
Now switching to C++11 I do not know how to implement the fact, that in private section I have got members, to which I have an direct access.
Could anyone explain me the way I can do the same using C++11 or C++14?
You should store a std::function and a std::tuple and then call the function on the tuple.
Here a working C++14 solution
#include <iostream>
#include <functional>
template<typename T1, typename ...T>
class Binder
{
public:
Binder(std::function<T1(T...)> f, std::tuple<T...> t) : m_functional_obj(f), m_parameters(t) {}
template<std::size_t ...I>
T1 callImpl(std::index_sequence<I...>)
{
return m_functional_obj(std::get<I>(m_parameters)...);
}
T1 callFunctionalObject()
{
return callImpl(std::index_sequence_for<T...>{});
}
private:
std::function<T1(T...)> m_functional_obj;
std::tuple<T...> m_parameters;
};
int test(int i)
{
std::cout << "test(" << i << ")" << std::endl;
return i + 1;
}
int main()
{
Binder<int,int> bibi(test, std::make_tuple<int>(2));
auto res = bibi.callFunctionalObject();
std::cout << "res is " << res << std::endl;
}
Live code
My example:
// Indices
template <std::size_t... Is>
struct Indices {};
template <std::size_t N, std::size_t... Is>
struct BuildIndices : BuildIndices <N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct BuildIndices<0, Is...> : Indices < Is... > {};
template<class FuncObject, class ... T>
class Binder
{
public:
Binder(FuncObject funcObject, T... args)
: m_funcObject(funcObject), m_arguments(std::make_tuple(args...))
{
}
void Call()
{
DoCall(BuildIndices<sizeof ... (T)> {});
}
private:
template<size_t... Ind>
void DoCall(Indices<Ind...>)
{
return m_funcObject(std::get<Ind>(m_arguments)...);
}
FuncObject m_funcObject;
std::tuple<T...> m_arguments;
};
void Foo(int, char)
{
}
int main()
{
Binder<void(*)(int, char), int, char> f(Foo, 1, 'd');
f.Call();
return 0;
}
The simplest way is to store an std::function object with already-set arguments using std::bind:
class Binder{
public:
template <typename T1, typename... T2>
Binder(T1 functionalObject, T2... args) : f(std::bind(functionalObject, args...)) {}
void callFunctionalObject() { f(); }
private:
std::function<void()> f;
};
void foo(int n, std::string s) {
std::cout << n << " " << s << std::endl;
}
int main()
{
Binder b(foo, 42, "test");
b.callFunctionalObject();
}
If you need something more advanced, then you might want to store the function arguments in and std::tuple and then use some template magic to unwrap it, but please specify what exactly do you need in the question.
P.S. See also "unpacking" a tuple to call a matching function pointer
In my current setup, I have a
typedef std::function<void (MyClass&, std::vector<std::string>) MyFunction;
std::map<std::string, MyFunction> dispatch_map;
And I register my functions in it with a macro. However, I have a problem with this: the parameters are passed as a vector of strings, which I have to convert inside the functions. I would rather do this conversion outside the functions, at the dispatcher level. Is this possible? The function signatures are known at compile time, and never change at run time.
You can get pretty far with variadic templates and some template/virtual techniques. With the following codes, you'll be able to do something like:
std::string select_string (bool cond, std::string a, std::string b) {
return cond ? a : b;
}
int main () {
Registry reg;
reg.set ("select_it", select_string);
reg.invoke ("select_it", "1 John Wayne"));
reg.invoke ("select_it", "0 John Wayne"));
}
output:
John
Wayne
Full implementation:
These codes are exemplary. You should optimize it to provide perfect forwarding less redundancy in parameter list expansion.
Headers and a test-function
#include <functional>
#include <string>
#include <sstream>
#include <istream>
#include <iostream>
#include <tuple>
std::string select_string (bool cond, std::string a, std::string b) {
return cond ? a : b;
}
This helps us parsing a string and putting results into a tuple:
//----------------------------------------------------------------------------------
template <typename Tuple, int Curr, int Max> struct init_args_helper;
template <typename Tuple, int Max>
struct init_args_helper<Tuple, Max, Max> {
void operator() (Tuple &, std::istream &) {}
};
template <typename Tuple, int Curr, int Max>
struct init_args_helper {
void operator() (Tuple &tup, std::istream &is) {
is >> std::get<Curr>(tup);
return init_args_helper<Tuple, Curr+1, Max>() (tup, is);
}
};
template <int Max, typename Tuple>
void init_args (Tuple &tup, std::istream &ss)
{
init_args_helper<Tuple, 0, Max>() (tup, ss);
}
This unfolds a function pointer and a tuple into a function call (by function-pointer):
//----------------------------------------------------------------------------------
template <int ParamIndex, int Max, typename Ret, typename ...Args>
struct unfold_helper;
template <int Max, typename Ret, typename ...Args>
struct unfold_helper<Max, Max, Ret, Args...> {
template <typename Tuple, typename ...Params>
Ret unfold (Ret (*fun) (Args...), Tuple tup, Params ...params)
{
return fun (params...);
}
};
template <int ParamIndex, int Max, typename Ret, typename ...Args>
struct unfold_helper {
template <typename Tuple, typename ...Params>
Ret unfold (Ret (*fun) (Args...), Tuple tup, Params ...params)
{
return unfold_helper<ParamIndex+1, Max, Ret, Args...> ().
unfold(fun, tup, params..., std::get<ParamIndex>(tup));
}
};
template <typename Ret, typename ...Args>
Ret unfold (Ret (*fun) (Args...), std::tuple<Args...> tup) {
return unfold_helper<0, sizeof...(Args), Ret, Args...> ().unfold(fun, tup);
}
This function puts it together:
//----------------------------------------------------------------------------------
template <typename Ret, typename ...Args>
Ret foo (Ret (*fun) (Args...), std::string mayhem) {
// Use a stringstream for trivial parsing.
std::istringstream ss;
ss.str (mayhem);
// Use a tuple to store our parameters somewhere.
// We could later get some more performance by combining the parsing
// and the calling.
std::tuple<Args...> params;
init_args<sizeof...(Args)> (params, ss);
// This demondstrates expanding the tuple to full parameter lists.
return unfold<Ret> (fun, params);
}
Here's our test:
int main () {
std::cout << foo (select_string, "0 John Wayne") << '\n';
std::cout << foo (select_string, "1 John Wayne") << '\n';
}
Warning: Code needs more verification upon parsing and should use std::function<> instead of naked function pointer
Based on above code, it is simple to write a function-registry:
class FunMeta {
public:
virtual ~FunMeta () {}
virtual boost::any call (std::string args) const = 0;
};
template <typename Ret, typename ...Args>
class ConcreteFunMeta : public FunMeta {
public:
ConcreteFunMeta (Ret (*fun) (Args...)) : fun(fun) {}
boost::any call (std::string args) const {
// Use a stringstream for trivial parsing.
std::istringstream ss;
ss.str (args);
// Use a tuple to store our parameters somewhere.
// We could later get some more performance by combining the parsing
// and the calling.
std::tuple<Args...> params;
init_args<sizeof...(Args)> (params, ss);
// This demondstrates expanding the tuple to full parameter lists.
return unfold<Ret> (fun, params);
}
private:
Ret (*fun) (Args...);
};
class Registry {
public:
template <typename Ret, typename ...Args>
void set (std::string name, Ret (*fun) (Args...)) {
funs[name].reset (new ConcreteFunMeta<Ret, Args...> (fun));
}
boost::any invoke (std::string name, std::string args) const {
const auto it = funs.find (name);
if (it == funs.end())
throw std::runtime_error ("meh");
return it->second->call (args);
}
private:
// You could use a multimap to support function overloading.
std::map<std::string, std::shared_ptr<FunMeta>> funs;
};
One could even think of supporting function overloading with this, using a multimap and dispatching decisions based on what content is on the passed arguments.
Here's how to use it:
int main () {
Registry reg;
reg.set ("select_it", select_string);
std::cout << boost::any_cast<std::string> (reg.invoke ("select_it", "0 John Wayne")) << '\n'
<< boost::any_cast<std::string> (reg.invoke ("select_it", "1 John Wayne")) << '\n';
}
If you can use boost, then here's an example of what I think you're trying to do ( although might work with std as well, I stick with boost personally ):
typedef boost::function<void ( MyClass&, const std::vector<std::string>& ) MyFunction;
std::map<std::string, MyFunction> dispatch_map;
namespace phx = boost::phoenix;
namespace an = boost::phoenix::arg_names;
dispatch_map.insert( std::make_pair( "someKey", phx::bind( &MyClass::CallBack, an::_1, phx::bind( &boost::lexical_cast< int, std::string >, phx::at( an::_2, 0 ) ) ) ) );
dispatch_map["someKey"]( someClass, std::vector< std::string >() );
However, as this sort of nesting quickly becomes fairly unreadable, it's usually best to either create a helper ( free function, or better yet a lazy function ) that does the conversion.
If I understand you correctly, you want to register void MyClass::Foo(int) and void MyClass::Bar(float), accepting that there will be a cast from std::string to int or float as appropriate.
To do this, you need a helper class:
class Argument {
std::string s;
Argument(std::string const& s) : s(s) { }
template<typename T> operator T { return boost::lexical_cast<T>(s); }
};
This makes it possible to wrap both void MyClass::Foo(int) and void MyClass::Bar(float) in a std::function<void(MyClass, Argument))>.
Interesting problme. This is indeen not trivial in C++, I wrote a self-contained implementation in C++11. It is possible to do the same in C++03 but the code would be (even) less readable.
#include <iostream>
#include <sstream>
#include <string>
#include <functional>
#include <vector>
#include <cassert>
#include <map>
using namespace std;
// string to target type conversion. Can replace with boost::lexical_cast.
template<class T> T fromString(const string& str)
{ stringstream s(str); T r; s >> r; return r; }
// recursive construction of function call with converted arguments
template<class... Types> struct Rec;
template<> struct Rec<> { // no parameters
template<class F> static void call
(const F& f, const vector<string>&, int) { f(); }
};
template<class Type> struct Rec< Type > { // one parameter
template<class F> static void call
(const F& f, const vector<string>& arg, int index) {
f(fromString<Type>(arg[index]));
}
};
template<class FirstType, class... NextTypes>
struct Rec< FirstType, NextTypes... > { // many parameters
template<class F> static void call
(const F& f, const vector<string>& arg, int index) {
Rec<NextTypes...>::call(
bind1st(f, fromString<FirstType>(arg[index])), // convert 1st param
arg,
index + 1
);
}
};
template<class... Types> void call // std::function call with strings
(const function<void(Types...)>& f, const vector<string>& args) {
assert(args.size() == sizeof...(Types));
Rec<Types...>::call(f, args, 0);
}
template<class... Types> void call // c function call with strings
(void (*f)(Types...), const vector<string>& args) {
call(function<void(Types...)>(f), args);
}
// transformas arbitrary function to take strings parameters
template<class F> function<void(const vector<string>&)> wrap(const F& f) {
return [&] (const vector<string>& args) -> void { call(f, args); };
}
// the dynamic dispatch table and registration routines
map<string, function<void(const vector<string>&)> > table;
template<class F> void registerFunc(const string& name, const F& f) {
table.insert(make_pair(name, wrap(f)));
}
#define smartRegister(F) registerFunc(#F, F)
// some dummy functions
void f(int x, float y) { cout << "f: " << x << ", " << y << endl; }
void g(float x) { cout << "g: " << x << endl; }
// demo to show it all works;)
int main() {
smartRegister(f);
smartRegister(g);
table["f"]({"1", "2.0"});
return 0;
}
Also, for performances, it's better to use unordered_map instead of map, and maybe avoid std::function overhead if you only have regular C functions. Of course this is only meaningful if dispatch time is significant compared to functions run-times.
No, C++ provides no facility for this to occur.
There are a lot of impressive Boost libraries such as Boost.Lambda or Boost.Phoenix which go a long way towards making C++ into a truly functional language. But is there a straightforward way to create a composite function from any 2 or more arbitrary functions or functors?
If I have: int f(int x) and int g(int x), I want to do something like f . g which would statically generate a new function object equivalent to f(g(x)).
This seems to be possible through various techniques, such as those discussed here. Certainly, you can chain calls to boost::lambda::bind to create a composite functor. But is there anything in Boost which easily allows you to take any 2 or more functions or function objects and combine them to create a single composite functor, similar to how you would do it in a language like Haskell?
To anyone stumbling onto this page, there's a great blog post on this subject from bureau14:
http://blog.quasardb.net/function-composition-in-c11/
This takes advantage of the new features in C++ 11 as well as using boost.
Stumbling upon this question, I'd like to point out to anyone who comes across this today that this is possible with a relatively elegant syntax using just the standard library and a few helper classes thanks to decltype, auto, and perfect forwarding.
Defining these two classes:
template <class Arg, class ArgCall, class OuterCall>
class pipe {
private:
ArgCall argcall;
OuterCall outercall;
public:
typedef pipe<Arg, ArgCall, OuterCall> this_type;
pipe(ArgCall ac, OuterCall oc) : argcall(ac), outercall(oc) {}
auto operator()(Arg arg) -> decltype(outercall(argcall(arg))) {
return outercall(argcall(arg));
}
template <class NewCall>
pipe<Arg, this_type, NewCall> operator[](NewCall&& nc) {
return {*this, std::forward<NewCall>(nc)};
}
};
template <class Arg>
class pipe_source {
public:
typedef pipe_source<Arg> this_type;
Arg operator()(Arg arg) {
return arg;
}
template <class ArgCall, class OuterCall>
static pipe<Arg, ArgCall, OuterCall> create(ArgCall&& ac, OuterCall&& oc) {
return {std::forward<ArgCall>(ac), std::forward<OuterCall>(oc)};
}
template <class OuterCall>
pipe<Arg, this_type, OuterCall> operator[](OuterCall&& oc) {
return {*this, std::forward<OuterCall>(oc)};
}
};
A simple program:
int f(int x) {
return x*x;
}
int g(int x) {
return x-2;
}
int h(int x) {
return x/2;
}
int main() {
auto foo = pipe_source<int>::create(f, g);
//or:
auto bar = pipe_source<int>()[g][h];
std::cout << foo(10) << std::endl;
std::cout << bar(10) << std::endl;
return 0;
}
This has the added benefit that once it's in a pipe, as long as the return type is correct you can add another function f to the chain with pipe[f].
Then:
$ g++ test.cpp -o test -std=c++11
$ ./test
98
4
$
I don't know of anything that supports the syntax you wish for currently. However, it would be a simple matter to create one. Simply override * for functors (boost::function<> for example) so that it returns a composite functor.
template < typename R1, typename R2, typename T1, typename T2 >
boost::function<R1(T2)> operator * (boost::function<R1(T2)> const& f, boost::function<R2(T2)> const& g)
{
return boost::bind(f, boost::bind(g, _1));
}
Untested, but I suspect it's close if it doesn't work out of the box.
Template them.
template<typename T1> class FunctorOne {
FunctorOne(T1 newt)
: t(newt) {}
void operator()() {
t();
}
T1 t;
};
template<> class FunctorOne<void> {
void operator()() {
}
};
template<typename T1> class FunctorTwo {
FunctorOne(T1 newt)
: t(newt) {}
void operator()() {
t();
}
T1 t;
};
template<> class FunctorTwo<void> {
void operator()() {
}
};
FunctorOne<FunctorTwo<FunctorOne<FunctorTwo<void>>>>> strangefunctionobject(FunctorTwo(FunctorOne(FunctorTwo()));
Excellent use of typedefs is recommended.
Edit: Whoops. Turns out that type inference in constructors sucks. I'll get back in a minute with something that actually works :P
Even more edit:
If you wanted just functors rather than functionoids, you could just create a new instance, or even just use static functions.
template<typename T1, typename T2> class FunctorOne {
public:
static bool Call() {
T1::Call(T2::Call());
return true;
}
};
template<> class FunctorOne<void, void> {
public:
static bool Call() {
}
};
template<typename T1> class FunctorTwo {
public:
static bool Call() {
T1::Call();
}
};
template<> class FunctorTwo<void> {
public:
static bool Call() {
}
};
bool haicakes = FunctorOne<FunctorTwo<void>, FunctorTwo<void>>::Call();
This assumes that in any given function, you can handle each different signature somewhat manually. Use of decltype could help in this regard with a C++0x compiler.
C++11. No boost. No helper classes. Any amount of arguments. Just std::function and variadic templates.
template <typename F1, typename F2>
struct function_composition_traits : public function_composition_traits<decltype(&F1::operator()), decltype(&F2::operator())>
{};
template <typename ClassType1, typename ReturnType1, typename... Args1, typename ClassType2, typename ReturnType2, typename... Args2>
struct function_composition_traits<ReturnType1(ClassType1::*)(Args1...) const, ReturnType2(ClassType2::*)(Args2...) const>
{
typedef std::function<ReturnType2(Args1...)> composition;
template <typename Func1, typename Func2>
inline static composition compose(const Func1& f1, const Func2& f2) {
return [f1,f2](Args1... args) -> ReturnType2 { return f2(f1(std::forward<Args1>(args)...)); };
}
};
template <typename F1, typename F2>
typename function_composition_traits<F1,F2>::composition compose(const F1& lambda1,const F2& lambda2)
{
return function_composition_traits<F1,F2>::template compose<F1,F2>(lambda1, lambda2);
}
template <typename F, typename... Fs>
auto compose(F f, Fs... fs) -> decltype(compose(f, compose(fs...)))
{
return compose(f, compose(std::forward<Fs>(fs)...));
}
Usage:
auto add = [](int x, int y){ return x+y; };
auto mul = [](int x){ return x*2; };
auto divide = [](int x) { return (double)x / 3.0; };
auto test = compose(add, mul, divide);
cout << "Result: " << test(2,3);
Output:
Result: 3.33333
See this answer https://stackoverflow.com/a/27727236/286335.
Really short, easy and general.