Automatic dynamic_cast for arguments in std::function - c++

We have polymorphic classes A and B like:
struct A {
virtual ~A() {}
};
struct B final : public A {
void f() { std::cout << "f" << std::endl; }
};
I want to assign a variable with std::function<void(A*)> from the lambda function with the type of void(B*) without explicitly applying dynamic_cast for the arguments as
std::function<void(A*)> funcA = [](A* a) {
[](B* b) { b->f(); }(dynamic_cast<B*>(a));
};
B b;
funcA(&b);
Are there any ways to automatically achieve this without wrapping the internal function with [](A* a){}?

I set off with the goal of making the following syntax work:
std::function<void(A*)> funcA = dynStdFunc([](B* b) { b->f(); });
To this end, dynStdFunc must:
Detect the parameters of the provided lambda;
Detect the parameters of funcA;
This isn't actually needed on our side, see the update at the end.
Generate a new functor, which glues both parameter lists together via dynamic_cast.
1. Detecting parameters has alrady been the subject of another answer of mine. We can use the following type trait:
// C++17's void_t
template <class...>
using void_t = void;
// Pack of arbitrary types
template <class...>
struct pack { };
namespace detail_parameters {
template <class F, class = void_t<>>
struct parameters { };
template <class F>
struct parameters<F, void_t<decltype(&F::operator ())>>
: parameters<decltype(&F::operator ())> { };
template <class R, class... Params>
struct parameters<R(Params...)> { using type = pack<Params...>; };
// More specializations for functions, function pointers,
// member function pointers...
}
// Retrieve the parameter list from a functionoid
template <class F>
using parameters = typename detail_parameters::parameters<std::remove_reference_t<F>>::type;
This takes in a functionoid type, and returns a pack<T...> containing its parameter types. Great.
2. the parameters required by the std::function aren't known from inside dynStdFunc. The way we make this work is by returning a temporary object, which contains a template for a conversion operator to std::function<Ret(Args...)>.
namespace detail_dynStdFunc {
// F = functionoid, Ps = pack of its parameters
template <class F, class Ps>
struct wrapper;
template <class F, class... Ps>
struct wrapper<F, pack<Ps...>> {
template <class Ret, class... Args>
operator std::function<Ret(Args...)> () {
// Now we know what parameters the `std::function` needs
}
F f;
};
}
template <class F>
auto dynStdFunc(F &&f) {
return detail_dynStdFunc::wrapper<
std::remove_reference_t<F>,
parameters<F>
>{std::forward<F>(f)};
}
3. We've got all we need, generating the new functor is straightforward:
template <class Ret, class... Args>
operator std::function<Ret(Args...)> () {
return [f_ = std::move(f)](Args... args) -> Ret {
return f_(dynamic_cast<Ps>(args)...);
};
}
And that's it! You can see it working live on Coliru.
Update: turns out I've done twice the work I needed to, because std::function can actually instantiate and wrap generic functors directly. Thanks Yakk!
So performing the conversion ourselves is pointless -- let's drop the wrapper:
template <class F, class... Ps>
auto dynStdFunc(F &&f, pack<Ps...>) {
return [f_ = std::forward<F>(f)](auto *... args) -> decltype(auto) {
return f_(dynamic_cast<Ps>(args)...);
};
}
template <class F>
auto dynStdFunc(F &&f) {
return dynStdFunc(std::forward<F>(f), parameters<F>{});
}
See it live on Coliru.

Related

Can template infer type of argument of std::function? [duplicate]

Basically, what I want to be able to do is take a lambda with any number of any type of parameters and convert it to an std::function.
I've tried the following and neither method works.
std::function([](){});//Complains that std::function is missing template parameters
template <typename T> void foo(function<T> f){}
foo([](){});//Complains that it cannot find a matching candidate
The following code does work however, but it is not what I want because it requires explicitly stating the template parameters which does not work for generic code.
std::function<void()>([](){});
I've been mucking around with functions and templates all evening and I just can't figure this out, so any help would be much appreciated.
As mentioned in a comment, the reason I'm trying to do this is because I'm trying to implement currying in C++ using variadic templates. Unfortunately, this fails horribly when using lambdas. For example, I can pass a standard function using a function pointer.
template <typename R, typename...A>
void foo(R (*f)(A...)) {}
void bar() {}
int main() {
foo(bar);
}
However, I can't figure out how to pass a lambda to such a variadic function. Why I'm interested in converting a generic lambda into an std::function is because I can do the following, but it ends up requiring that I explicitly state the template parameters to std::function which is what I am trying to avoid.
template <typename R, typename...A>
void foo(std::function<R(A...)>) {}
int main() {
foo(std::function<void()>([](){}));
}
You can't pass a lambda function object as an argument of type std::function<T> without explicitly specifying the template argument T. Template type deduction tries to match the type of your lambda function to the std::function<T> which it just can't do in this case - these types are not the same. Template type deduction doesn't consider conversions between types.
It is possible if you can give it some other way to deduce the type. You can do this by wrapping the function argument in an identity type so that it doesn't fail on trying to match the lambda to std::function (because dependent types are just ignored by type deduction) and giving some other arguments.
template <typename T>
struct identity
{
typedef T type;
};
template <typename... T>
void func(typename identity<std::function<void(T...)>>::type f, T... values) {
f(values...);
}
int main() {
func([](int x, int y, int z) { std::cout << (x*y*z) << std::endl; }, 3, 6, 8);
return 0;
}
This is obviously not useful in your situation though because you don't want to pass the values until later.
Since you don't want to specify the template parameters, nor do you want to pass other arguments from which the template parameters can be deduced, the compiler won't be able to deduce the type of your std::function argument.
TL;DR: What you ask can be done using CTAD, a feature that enables you to create an std::function of the expected type, right at the call site without spelling out the template arguments:
foo(std::function([](int arg){ return Bar{}; }));
// ^^^^^^^^^^^^^ constructor call w/o templates
// std::function<Bar(int)> will be auto-deduced
Demo
If you are interested on how to emulate the mechanics of such a deduction, or need to work with a pre c++17 compiler, check the rest of the answer.
You can use a dedicated/retrospective cast. Once you have a tool like this
#include <functional>
using namespace std;
template<typename T>
struct memfun_type
{
using type = void;
};
template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const>
{
using type = std::function<Ret(Args...)>;
};
template<typename F>
typename memfun_type<decltype(&F::operator())>::type
FFL(F const &func)
{ // Function from lambda !
return func;
}
you can say FFL() to all lambda types to have them converted to what would be the correct version of std::function
template <typename... Args> void Callback(std::function<void(Args...)> f){
// store f and call later
}
int main()
{
Callback(FFL([](int a, float b){
// do something
}));
return 0;
}
Display
As shown at Inferring the call signature of a lambda or arbitrary callable for "make_function", you can infer the calling signature of a lambda (or any other functor with a single calling signature) from its (single) operator():
template<typename T> struct remove_class { };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...)> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };
template<typename T>
struct get_signature_impl { using type = typename remove_class<
decltype(&std::remove_reference<T>::type::operator())>::type; };
template<typename R, typename... A>
struct get_signature_impl<R(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(&)(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(*)(A...)> { using type = R(A...); };
template<typename T> using get_signature = typename get_signature_impl<T>::type;
This is a rather inflexible approach, though; as R. Martinho Fernandes says, it won't work for functors with multiple operator()s, nor for functors with templated operator() or for (C++14) polymorphic lambdas. This is why bind defers inference of its result type until the eventual call attempt.
It is possible to get the needed std::function type for lambda using derivation, decltype, variadic templates and a few type traits:
namespace ambient {
template <typename Function>
struct function_traits : public function_traits<decltype(&Function::operator())> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
typedef ReturnType (*pointer)(Args...);
typedef const std::function<ReturnType(Args...)> function;
};
template <typename Function>
typename function_traits<Function>::function to_function (Function& lambda) {
return static_cast<typename function_traits<Function>::function>(lambda);
}
template <class L>
struct overload_lambda : L {
overload_lambda(L l) : L(l) {}
template <typename... T>
void operator()(T&& ... values){
// here you can access the target std::function with
to_function(*(L*)this)(std::forward<T>(values)...);
}
};
template <class L>
overload_lambda<L> lambda(L l){
return overload_lambda<L>(l);
}
}
I use it in my code like this:
ambient::lambda([&](const vector<int>& val){
// some code here //
})(a);
PS: in my real case I then save this std::function object and its arguments inside a generic kernel objects that I can execute later on demand via virtual functions.
Isn't currying already implemented with std::bind?
auto sum = [](int a, int b){ return a+b; };
auto inc = std::bind( sum, _1, 1 );
assert( inc(1)==2 );
This could be interesting for you: https://gist.github.com/Manu343726/94769034179e2c846acc
That is an experiment I have written a month ago. The goal was to create a functor-like C++ template which emulates Haskell's partial calls closures, i.e. the automatic creation of a closure of m-n argumments when you call with n argumments a function with m parameters.
This is one example of what this experiment is cappable to do:
int f( int a, int b, int c, int d)
{
return a+b+c+d;
}
int main()
{
auto foo = haskell::make_function( f );
auto a = foo , 1 , 2 , 3; //a is a closure function object with one parameter
std::cout << a , 4 << std::endl; //Prints 10
}
haskell::make_function uses some type traits to take care of the different types of function entities, lambdas included:
auto f = haskell::make_function( []( int x, int y , int z ){ return x*y*z; } );
auto a = f(1,2); //a is functor with one parameter (Using the alternative C++-like syntax)
auto b = a(3); // b is 6
As you can see, I use comma operator to mmimic Haskell syntax, but you could change it to the call operator to achieve your goal syntax.
Your are completely free to do anything you want with the code (Check the license).
In C++17 there is the constructor type deduction. So you can save some typing for the std::function template arguments. This is not quite nothing, but a bit less.
template <typename R, typename...A>
void foo(std::function<R(A...)>) {}
int main() {
foo(std::function([](){}));
}
Seven years later and probably the simplest solution then, still works today.
template< char const * (*name) () >
struct user {
auto id() { return name(); }
} ;
Usage
constexpr auto lama () { return "Lama"; }
int main( int , char * [] )
{
auto amuser = user< lama >{} ;
cout << boolalpha << amuser.id() << endl ;
}
Lambda afficionados are served too
auto cat = [] () constexpr { return "Cat"; } ;
auto sneaky = user< cat >{} ;
cout << boolalpha << sneaky.id() << endl ;
With lambda expressions that have explicit template parameter lists (C++20 feature), you can write the function much easier as shown below:
template <typename F,typename... T>
auto func(F f, T... values) {
return f(values...);
}
int main() {
auto result = func([]<typename... T>(T...args){
return (...*args);
},1,2,3,6,22);
std::cout<<result<<"\n";
}
with std::result_of, if you use only function (no class/struct, 'cause the declaration would be nothing like the std::function, and it really ugly),you can now make it like:
template <typename Func, typename ...Args>
std::result_of_t<Func(Args...)> func(Func function, Args... args) {
/// now do your staff here
}
/// usage:
func([](){printf("lambda function\n"});

How can I have a function pointer template as a template parameter?

I am trying to create a class template that expects a type and a function pointer as template parameters. The function pointer is expected to be a member function of the type passed in. I want the user of the class template to be able to pass in a void member function of the type passed in. That member function will then be called on instances of the type passed in every time a certain function of the class template is called. It's a bit hard to explain but it's supposed to work sort of like this:
template<Type, Function> // For the purpose of explaining it
class Foo
{
public:
template<Args... args>
void callOnAll(Args... args)
{
for(Type* ptr : ptrs_)
{
ptr->Function(std::forward<Args>(args)...);
}
}
private:
std::vector<Type*> ptrs_;
}
Assuming that something like this is possible (which I realize it might not be), the key would have to be getting the template parameters for the class right, and getting the update function right. This is what I've come up with but I still can't get it to work:
template<typename T, template<typename... Args> void(T::*func)(Args... args)>
class EngineSystem
{
public:
template<typename... Args>
void update(Args... args)
{
for (T* handler : handlers_)
{
((*handler).*func)(std::forward<Args>(args)...);
}
}
private:
std::vector<T*> handlers_;
};
The code above does not compile. It points me to the line where I declare the template parameters for the class, underlines void and says expected 'class' or 'typename'.
Is it clear what I'm trying to achieve, and is it possible?
C++ doesn't allow non-type template template parameters. That means you can't have a parameter-pack for your member-function pointer parameter.
Assuming you're using C++17 or newer, you can use an auto template parameter instead:
template<typename T, auto func>
public:
template<typename... Args>
void update(Args... args)
{
for (T* handler : handlers_)
{
(handler->*func)(std::forward<Args>(args)...);
}
}
private:
std::vector<T*> handlers_;
};
Live Demo
Technically that will accept any object for func, but assuming update is called, then (handler->*func)(std::forward<Args>(args)...) still has to be well-formed or compilation will fail.
If you want compilation to fail even if update never gets called, you could use some type traits and a static_assert (or some SFINAE hackery, if you need it) to ensure that func is actually a pointer to a member function of T:
template <typename T, typename U>
struct IsPointerToMemberOf : std::false_type {};
template <typename T, typename U>
struct IsPointerToMemberOf<T, U T::*> : std::true_type {};
template <typename T, typename U>
struct IsPointerToMemberFunctionOf
: std::integral_constant<
bool,
IsPointerToMemberOf<T, U>::value && std::is_member_function_pointer<U>::value
>
{};
template<typename T, auto func>
class EngineSystem
{
static_assert(IsPointerToMemberFunctionOf<T, decltype(func)>::value, "func must be a pointer to a member function of T");
//...
};
Live Demo
#include <iostream>
#include <vector>
template <typename T, typename... Args>
class EngineSystem
{
public:
EngineSystem(void(T::*fun)(Args... args)): fun(fun)
{
}
void update(Args... args)
{
for (T* handler : handlers_)
{
(handler->*fun)(std::forward<Args>(args)...);
}
}
void push(T* t){
handlers_.push_back(t);
}
private:
void(T::*fun)(Args... args);
std::vector<T*> handlers_;
};
struct A {
int x = 3;
void fn(int a, int b){
std::cout << a << b << x;
}
};
template <typename T, typename... Args>
auto makeEngine(void(T::*fun)(Args... args)){
return EngineSystem<T, Args...>(fun);
}
int main() {
EngineSystem<A, int, int> as(&A::fn);
// or deduce types automatically
auto es = makeEngine(&A::fn);
A a;
es.push(&a);
es.update(1,2);
return 0;
}
https://gcc.godbolt.org/z/Pcdf9K9nz

Variadic template parameter order problem

I have a templated function wrapper that I am attempting to update to C++11 syntax (variadic paremeters).
My issue is that I am caught in a "catch 22" where 'Args...' must be the last template parameter, but at the same time, cannot be defined after the function pointer template parameter.
Any idea if this can actually be solved?
template <typename... Args, void(*Function)(Args...)>
class function
{
public:
void operator ()(Args... args) const
{
(*Function)(std::forward<Args...>(args...));
}
};
A possible way is to use the template specialization
template <typename>
struct myFunc;
template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
{
// ...
};
but, this way, you intercept (as template parameter) the type of the function pointer, not the function pointer itself; so you have to pass the function pointer in some way (constructor?).
Also observe that, if you want to use perfect forwarding, you have to transform operator() in a template method receiving arguments as universal references (&&).
Something as follows
template <typename ... As>
R operator() (As && ... args) const
{
return fun(std::forward<As>(args)...);
}
where fun is a pointer of type R(*)(Args...).
The following is a full compiling example
#include <iostream>
#include <utility>
int foo (int, long)
{ return 42; }
template <typename>
struct myFunc;
template <typename R, typename ... Args>
struct myFunc<R(*)(Args...)>
{
using funPnt = R(*)(Args...);
funPnt fun = nullptr;
myFunc (funPnt f0) : fun{f0}
{ }
template <typename ... As>
R operator() (As && ... args) const
{
return fun(std::forward<As>(args)...);
}
};
int main ()
{
myFunc<decltype(&foo)> mf0{&foo};
std::cout << mf0(1, 2l) << std::endl;
}
If you really want the pointer function as template parameter (but, this way, every function determine a different type; this can be a good or a bad thing according to your needs), you can write the myFunc struct receiving before a type (the same pointer type) and then a value of that type.
So
template <typename T, T>
struct myFunc;
template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<R(*)(Args...), Func>
{
template <typename ... As>
R operator() (As && ... args) const
{
return Func(std::forward<As>(args)...);
}
};
that can be declared
myFunc<decltype(&foo), foo> mf0;
If you can use C++17, you can simplify using auto for type of template values; so you can avoid the type
template <auto>
struct myFunc;
template <typename R, typename ... Args, R(*Func)(Args...)>
struct myFunc<Func>
{
template <typename ... As>
R operator() (As && ... args) const
{
return Func(std::forward<As>(args)...);
}
};
and you can create a myFunc object as follows
myFunc<&foo> mf0;
Addendum: if you can use C++17, you can define a deduction guide for the first example (pointer as member, not as template value parameter)
template <typename R, typename ... Args>
myFunc (R(*)(Args...)) -> myFunc<R(*)(Args...)>;
so, instead of
myFunc<decltype(&foo)> mf0{&foo};
you can simply write
myFunc mf0{&foo};
Off Topic: I hope that you know that you're reinventing the wheel. As suggested by NathanOliver, the standard provide std::function.

Is it possible to place function pointer in template parameter ahead of dependent type?

I have a template that has a function pointer as it's 2nd parameter and a type that the function pointer is dependent on as it's first.
i.e.
template <typename P, typename void(*fn)(P)>
auto function(P) -> otherType<P, fn>;
I want to make it so that I can just specify the function pointer in the template list without having to specify the dependent type as that type should somehow be able to be inferred from the function pointer that I specify (or maybe even the parameter list, but I think that it probably is too far down the line).
My first thought was to defer the conversion to a template parameter value, by passing a template typename and then convert to a value after the fact though template metaprogramming wizardry.
i.e.
template <typename F, typename P>
auto function(P) -> [[ something here to get otherType<P, fn> if F was a function pointer ]]
However, I'm not sure how I can do this. Any ideas?
Edit
What I'm trying to accomplish here is to make a helper function that will generate a class object. So, given what was said by StenSoft, this is what I've come up with. Unfortunately it doesn't work with a failure inside the main() function where it cannot match to the correct function due to deduction failure:
#include <iostream>
#include <functional>
template<typename T, typename F>
struct wrapper_fntor
{
T m_t;
F m_f;
wrapper_fntor(T t, F f) : m_t(t), m_f(f) {}
void invoke() { m_f(m_t); }
};
template<typename T, void(*fn)(T)>
struct wrapper_fn
{
T m_t;
wrapper_fn(T t) : m_t(t) {}
void invoke() { fn(m_t); }
};
template <typename T>
struct Wrapper;
template <typename Ret, typename P>
struct Wrapper<Ret(P)>
{
template <Ret(*fn)(P)>
static Ret function(P p)
{
return fn(std::forward<P>(p));
}
template <Ret(*fn)(P)>
static P get_param_type(P);
typedef decltype(get_param_type<Ret(P)>()) param_t;
};
template<typename F>
wrapper_fn<typename Wrapper<F>::param_t, &Wrapper<F>::function> make_wrapper(typename Wrapper<F>::param_t param)
{
return wrapper_fn<typename Wrapper<F>::param_t, &Wrapper<F>::function>(param);
}
template<typename F>
wrapper_fntor<typename Wrapper<F>::param_t, F> make_wrapper(typename Wrapper<F>::param_t param, F fntor)
{
return wrapper_fntor<typename Wrapper<F>::param_t, F>(param, fntor);
}
void function(int value)
{
std::cout << "function called " << value << std::endl;
}
int main()
{
auto x = make_wrapper<function>(3);
x.invoke();
}
demo
For a similar problem I have used a templated function inside a templated wrapper class and a macro (this actually works with any parameters and return type):
template <typename T>
struct Wrapper;
template <typename Ret, typename... Params>
struct Wrapper<Ret(Params...)>
{
template <Ret(*fn)(Params...)>
static Ret function(Params... params)
{
return fn(std::forward<Params>(params)...);
}
};
#define FUNCTION(fn) \
Wrapper<decltype(fn)>::function<fn>

How to convert a lambda to an std::function using templates

Basically, what I want to be able to do is take a lambda with any number of any type of parameters and convert it to an std::function.
I've tried the following and neither method works.
std::function([](){});//Complains that std::function is missing template parameters
template <typename T> void foo(function<T> f){}
foo([](){});//Complains that it cannot find a matching candidate
The following code does work however, but it is not what I want because it requires explicitly stating the template parameters which does not work for generic code.
std::function<void()>([](){});
I've been mucking around with functions and templates all evening and I just can't figure this out, so any help would be much appreciated.
As mentioned in a comment, the reason I'm trying to do this is because I'm trying to implement currying in C++ using variadic templates. Unfortunately, this fails horribly when using lambdas. For example, I can pass a standard function using a function pointer.
template <typename R, typename...A>
void foo(R (*f)(A...)) {}
void bar() {}
int main() {
foo(bar);
}
However, I can't figure out how to pass a lambda to such a variadic function. Why I'm interested in converting a generic lambda into an std::function is because I can do the following, but it ends up requiring that I explicitly state the template parameters to std::function which is what I am trying to avoid.
template <typename R, typename...A>
void foo(std::function<R(A...)>) {}
int main() {
foo(std::function<void()>([](){}));
}
You can't pass a lambda function object as an argument of type std::function<T> without explicitly specifying the template argument T. Template type deduction tries to match the type of your lambda function to the std::function<T> which it just can't do in this case - these types are not the same. Template type deduction doesn't consider conversions between types.
It is possible if you can give it some other way to deduce the type. You can do this by wrapping the function argument in an identity type so that it doesn't fail on trying to match the lambda to std::function (because dependent types are just ignored by type deduction) and giving some other arguments.
template <typename T>
struct identity
{
typedef T type;
};
template <typename... T>
void func(typename identity<std::function<void(T...)>>::type f, T... values) {
f(values...);
}
int main() {
func([](int x, int y, int z) { std::cout << (x*y*z) << std::endl; }, 3, 6, 8);
return 0;
}
This is obviously not useful in your situation though because you don't want to pass the values until later.
Since you don't want to specify the template parameters, nor do you want to pass other arguments from which the template parameters can be deduced, the compiler won't be able to deduce the type of your std::function argument.
TL;DR: What you ask can be done using CTAD, a feature that enables you to create an std::function of the expected type, right at the call site without spelling out the template arguments:
foo(std::function([](int arg){ return Bar{}; }));
// ^^^^^^^^^^^^^ constructor call w/o templates
// std::function<Bar(int)> will be auto-deduced
Demo
If you are interested on how to emulate the mechanics of such a deduction, or need to work with a pre c++17 compiler, check the rest of the answer.
You can use a dedicated/retrospective cast. Once you have a tool like this
#include <functional>
using namespace std;
template<typename T>
struct memfun_type
{
using type = void;
};
template<typename Ret, typename Class, typename... Args>
struct memfun_type<Ret(Class::*)(Args...) const>
{
using type = std::function<Ret(Args...)>;
};
template<typename F>
typename memfun_type<decltype(&F::operator())>::type
FFL(F const &func)
{ // Function from lambda !
return func;
}
you can say FFL() to all lambda types to have them converted to what would be the correct version of std::function
template <typename... Args> void Callback(std::function<void(Args...)> f){
// store f and call later
}
int main()
{
Callback(FFL([](int a, float b){
// do something
}));
return 0;
}
Display
As shown at Inferring the call signature of a lambda or arbitrary callable for "make_function", you can infer the calling signature of a lambda (or any other functor with a single calling signature) from its (single) operator():
template<typename T> struct remove_class { };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...)> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) volatile> { using type = R(A...); };
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const volatile> { using type = R(A...); };
template<typename T>
struct get_signature_impl { using type = typename remove_class<
decltype(&std::remove_reference<T>::type::operator())>::type; };
template<typename R, typename... A>
struct get_signature_impl<R(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(&)(A...)> { using type = R(A...); };
template<typename R, typename... A>
struct get_signature_impl<R(*)(A...)> { using type = R(A...); };
template<typename T> using get_signature = typename get_signature_impl<T>::type;
This is a rather inflexible approach, though; as R. Martinho Fernandes says, it won't work for functors with multiple operator()s, nor for functors with templated operator() or for (C++14) polymorphic lambdas. This is why bind defers inference of its result type until the eventual call attempt.
It is possible to get the needed std::function type for lambda using derivation, decltype, variadic templates and a few type traits:
namespace ambient {
template <typename Function>
struct function_traits : public function_traits<decltype(&Function::operator())> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits<ReturnType(ClassType::*)(Args...) const> {
typedef ReturnType (*pointer)(Args...);
typedef const std::function<ReturnType(Args...)> function;
};
template <typename Function>
typename function_traits<Function>::function to_function (Function& lambda) {
return static_cast<typename function_traits<Function>::function>(lambda);
}
template <class L>
struct overload_lambda : L {
overload_lambda(L l) : L(l) {}
template <typename... T>
void operator()(T&& ... values){
// here you can access the target std::function with
to_function(*(L*)this)(std::forward<T>(values)...);
}
};
template <class L>
overload_lambda<L> lambda(L l){
return overload_lambda<L>(l);
}
}
I use it in my code like this:
ambient::lambda([&](const vector<int>& val){
// some code here //
})(a);
PS: in my real case I then save this std::function object and its arguments inside a generic kernel objects that I can execute later on demand via virtual functions.
Isn't currying already implemented with std::bind?
auto sum = [](int a, int b){ return a+b; };
auto inc = std::bind( sum, _1, 1 );
assert( inc(1)==2 );
This could be interesting for you: https://gist.github.com/Manu343726/94769034179e2c846acc
That is an experiment I have written a month ago. The goal was to create a functor-like C++ template which emulates Haskell's partial calls closures, i.e. the automatic creation of a closure of m-n argumments when you call with n argumments a function with m parameters.
This is one example of what this experiment is cappable to do:
int f( int a, int b, int c, int d)
{
return a+b+c+d;
}
int main()
{
auto foo = haskell::make_function( f );
auto a = foo , 1 , 2 , 3; //a is a closure function object with one parameter
std::cout << a , 4 << std::endl; //Prints 10
}
haskell::make_function uses some type traits to take care of the different types of function entities, lambdas included:
auto f = haskell::make_function( []( int x, int y , int z ){ return x*y*z; } );
auto a = f(1,2); //a is functor with one parameter (Using the alternative C++-like syntax)
auto b = a(3); // b is 6
As you can see, I use comma operator to mmimic Haskell syntax, but you could change it to the call operator to achieve your goal syntax.
Your are completely free to do anything you want with the code (Check the license).
In C++17 there is the constructor type deduction. So you can save some typing for the std::function template arguments. This is not quite nothing, but a bit less.
template <typename R, typename...A>
void foo(std::function<R(A...)>) {}
int main() {
foo(std::function([](){}));
}
Seven years later and probably the simplest solution then, still works today.
template< char const * (*name) () >
struct user {
auto id() { return name(); }
} ;
Usage
constexpr auto lama () { return "Lama"; }
int main( int , char * [] )
{
auto amuser = user< lama >{} ;
cout << boolalpha << amuser.id() << endl ;
}
Lambda afficionados are served too
auto cat = [] () constexpr { return "Cat"; } ;
auto sneaky = user< cat >{} ;
cout << boolalpha << sneaky.id() << endl ;
With lambda expressions that have explicit template parameter lists (C++20 feature), you can write the function much easier as shown below:
template <typename F,typename... T>
auto func(F f, T... values) {
return f(values...);
}
int main() {
auto result = func([]<typename... T>(T...args){
return (...*args);
},1,2,3,6,22);
std::cout<<result<<"\n";
}
with std::result_of, if you use only function (no class/struct, 'cause the declaration would be nothing like the std::function, and it really ugly),you can now make it like:
template <typename Func, typename ...Args>
std::result_of_t<Func(Args...)> func(Func function, Args... args) {
/// now do your staff here
}
/// usage:
func([](){printf("lambda function\n"});