Error when using parameter pack with std::function [duplicate] - c++

There are several questions on SO that relate to casting lambdas to std::functions, but I have yet to see one that uses a parameter pack for the argument list. This seems broken on my version of g++ (7.1.1-4), and possibly it's just not supported. So is this legal c++17 (by the standard)? If not, why?
#include <functional>
template <typename TReturn, typename ... TArgs>
void Functor(std::function<TReturn (TArgs...)> f) {}
int main(int argc, char * argv[]) {
auto x = [] (int a, int b) { return a * b; };
Functor<int, int, int>(x);
return 0;
}
The code above won't compile because it fails type deduction. Obviously explicitly typing x as std::function<int (int, int)> instead of using auto makes the error go away. But that doesn't allow me to pass an r-value to Functor as I would like. I would also like to not loose any type-safety by using another template parameter for the function type.
What I really don't understand is why the above code fails to compile, but the below code is fine and works:
#include <functional>
template <typename TReturn, typename TArgA, typename TArgB>
void Functor(std::function<TReturn (TArgA, TArgB)> f) {}
int main(int argc, char * argv[]) {
auto x = [] (int a, int b) { return a * b; };
Functor<int, int, int> (x);
return 0;
}

The issue is that the compiler doesn't know that you've intended int, int to be the whole of TArgs, and so tries to deduce the remainder of TArgs from the argument f.
For example, this would be valid:
Functor<int, int, int>(std::function<int(int, int, char, float)>{});
// TArgs := {int, int, [...] char, float}
So you need to instruct the compiler to not try to deduce the remainder of TArgs. For example, you could write:
(*Functor<int, int, int>)(x);
Or you could write Functor with a non-decomposed signature Sig:
template <Sig>
void Functor(std::function<Sig> f) {}
Or you could wrap the use of TArgs in the parameter f in a non-deduced context:
template <typename TReturn, typename ... TArgs>
void Functor(std::function<std::conditional_t<false, void, TReturn (TArgs...)>> f) {}

This fails:
#include <functional>
template <typename TReturn, typename ... TArgs>
void Functor(std::function<TReturn (TArgs...)> f) {}
int main(int argc, char * argv[]) {
auto x = [] (int a, int b) { return a * b; };
Functor<int, int, int>(x);
return 0;
}
because you're not specifying that the entirety of TArgs... is {int, int}. What you are doing is specifying that the first two types are {int, int}. Effectively, by providing those three types, we've turned the deduction problem into:
template <typename ... TArgs>
void Functor(std::function<int(int, int, TArgs...)> f) {}
int main(int argc, char * argv[]) {
auto x = [] (int a, int b) { return a * b; };
Functor(x);
return 0;
}
This doesn't compile because a lambda isn't a std::function (or derived from one), which is the same reason you couldn't have called this without having provided any types to begin with.
The non-variadic version doesn't have this problem, since you've provided all the types.
But really, what you want is:
template <typename F>
void Functor(F ) {}
This doesn't lose you any type safety. It's using std::function that loses type information, since that class template exists to type erase.

It is very rarely a good idea to cast a lambda to a std::function in a template if you are just going to call it. std::function is type-erasure, and templated type erasure only makes sense if you are going to "pass it on" somewhere else and/or return it.
In any case, try this:
template <class Sig>
void Functor(std::function<Sig> f) {}
int main(int argc, char * argv[]) {
auto x = [] (int a, int b) { return a * b; };
Functor<int(int, int)>(x);
return 0;
}
but you should really just do
template <class F>
void Functor(F f) {}
which is perfectly type-safe.
If you want early type checking, you could write
template<class Sig, class F>
struct signature_compatible;
template<class R, class...Args, class F>
struct signature_compatible<R(Args...), F> :
std::is_consructible< R, std::result_of_t<F(Args...)>>
{};
then do
template <class Sig, class F>
void Functor(F f) {
static_assert( signature_compatible<Sig, F&>::value, "bad signature" );
}
but only if you really need to.

Here is a solution that will let you call functor without specifying it's template argument:
#include <functional>
#include <type_traits>
template <class T> struct Fun_trait {};
template <class T, class... Args, class Ret>
struct Fun_trait<auto (T::*) (Args...) const -> Ret>
{
using F = std::function<auto (Args...) -> Ret>;
};
template <class TReturn, class... TArgs>
void functor(std::function<TReturn (TArgs...)> f) {}
template <class F>
std::void_t<decltype(&F::operator())>
functor(F f)
{
return functor<typename Fun_trait<decltype(&F::operator())>::F>(f);
};
int main(int argc, char * argv[])
{
auto x = [] (int a, int b) { return a * b; };
// nice and easy:
functor(x);
return 0;
}
This is just a lazy first draft to get you started. You need to expand it to support forwarding and non-const operator().
It works in 2 stages:
1st we have Fun_trait who - for pointer method types (e.g. the operator() of a lambda) - has defined an alias F for the required std::function argument type.
Next we have a overload of your function functor which via SFINAE with std::void_t kicks in only for functors with a non-overloaded operator() (e.g. a lambda) and then using the above trait calls the main function functor with the correct template argument deduced.

Related

template deduction guide fails with lambda but not global function

I have a simple class which stores a callable (either a lambda or global function) and a void*, both of which are passed on construction:
#include <iostream>
#include <vector>
#include <functional>
using namespace std;
template <typename>
class LyricAnatali;
template <typename Res, typename... Args>
class LyricAnatali<Res(Args...)> {
public:
template <typename F>
LyricAnatali(F&& f, void* data)
: m_ptr(f), m_userData(data) {}
private:
Res(*m_ptr)(void*, Args...) = nullptr;
void* m_userData;
};
// Deduction guide
template <typename Res, typename... Args>
LyricAnatali(Res(*)(void*, Args...), void*) -> LyricAnatali<Res(Args...)>;
int GlobalFunction(void*, const string& s, const vector<int>& t, int u) { return 0; }
int main() {
auto lg = [](void*, const string& s, const vector<int>& t, int u) -> int { return 0; };
LyricAnatali<int(const string& s, const vector<int>& t, int u)> func(lg, 0); // Compiles
auto lambda = LyricAnatali(lg, 0); // Does not compile
auto global = LyricAnatali(GlobalFunction, 0); // Compiles
auto stdFunc = std::function(lg); // Compiles
}
The line indicated above does not compile. From https://godbolt.org/z/7K3K48Tn4, I feel the relevant error is:
could not match 'Res (*)(void *, Args...)' against '(lambda at <source>:28:13)'
LyricAnatali(Res(*)(void*, Args...), void*) -> LyricAnatali<Res(Args...)>;
I don't understand enough about deduction guides to know how to fix this. Can someone please advise how I can get this to work when passing a lambda?
lambda is a class type with operator() (const in this case), and would not match a function pointer, you'd need to write deduction guide for that. (this is general template deduction rule, not limit to CTAD)
a possible implementation
template <typename...>
struct parse_member{};
template <typename R, typename G, typename... A>
struct parse_member<R(G::*)(void*, A...)const>{ // and all combination of const, noexcept, volatile, &, &&, for general case
using type = R(A...);
};
template <
typename F,
typename sig = typename parse_member<decltype(&F::operator())>::type
>
LyricAnatali(F, void*) -> LyricAnatali<sig>;
https://godbolt.org/z/sTsovGEvd

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 to write a template that can deduce a type use a function's argument type?

How to write a template that use function as template parameter, and auto deduce other typename by this function's argument type?
void foo(int *p) {}
template<typename T, void (*F)(T*)>
struct bar
{
bar(T* t)
{
F(t);
}
}
int *p;
bar<int, foo> b(p); // both int and foo are required here
how to write a template that supports to use only foo as argument
bar<foo> b(p);
If you can use c++17 with it's auto template parameter (like #n.m. said in the comments) you can use it as the template parameter and then the type T with type traits.
First off we need the standard type traits and also a type trait to get the argument to a unary function (your foo) that we can write like this:
#include <type_traits>
// Trait to get the argument type of a unary function
template<typename T>
struct unary_func_arg;
template<typename R, typename T>
struct unary_func_arg< R(*)(T) >
{
using type = T;
};
This will produce an error if you put anything other than a function pointer into it since the main specialization is not declared.
After this we can finally write bar as this:
template< auto F >
struct bar
{
// Assert it's a function pointer
static_assert( std::is_pointer_v<decltype(F)> );
static_assert( std::is_function_v< std::remove_pointer_t<decltype(F)> > );
// Get the parameter type
using T = typename unary_func_arg< decltype(F) >::type;
bar(T t)
{
F(t);
}
};
We have to make sure that F is a function pointer so we static assert that, then we get the type T from our type trait.
Now you can declare f and b like this:
int* p;
bar<foo> b(p);
EDIT: If you need T to be not a pointer so you can write T*, you can either make a type trait that removes 1 pointer level or modify the type trait here to as such:
// Trait to get the argument type of a unary function
template<typename T>
struct unary_func_arg_pointer;
template<typename R, typename T>
struct unary_func_arg_pointer< R(*)(T*) >
{
using type = T;
};
Now T will be just int in this example
In C++11 classes cannot deduce all the types of a passed function. But a function can.
So this function can be written:
template<typename Ret, typename Param>
Deduced_Types<Ret, Param> deduce_type(Ret (*)(Param))
{
return Deduced_Types<Ret, Param>();
}
This function uses a type to store the deduced types (it has to be declared before the function):
template<typename Ret, typename Param>
class Deduced_Types
{
public:
typedef Ret Return_type;
typedef Param Parameter_type;
};
Now to test it;
int f(bool)
{
return 0;
}
int main(int argc, char* argv[])
{
decltype( deduce_type(f) )::Return_type i = 0;
return i;
}
It works.
So Now to Bar:
template< class F >
class Bar
{
public:
typedef typename F::Return_type Func_Return_type;
typedef typename F::Parameter_type Fun_Param_type;
};
which has to be called:
Bar< decltype(deduce_type(f)) > b;
(this is where You can use a macro)
Works on gcc 4.8.1 : https://godbolt.org/z/1cz2pk
Edit:
Pre C++17 function could not be passed into a template.
So what is needed is that you need to pass the function pointer into the class. And a static_assert to verify the parameters are correct:
#include <type_traits>
struct bar
{
template<typename F, typename T>
bar(F f, T t)
{
typedef decltype(deduce_type(f)) D;
static_assert(std::is_same<typename D::Parameter_type, T>::value,"parameter has different type function parameter");
f(t);
}
};
Now instead of passing the function as a template parameter, the function pointer is passed in as a parameter:
void foo(int *p) {}
int *p;
bar b(foo, p);
Only problem here is that the class has to store this pointer for future use.
In C++17, you might do
template <auto> struct bar;
template<typename T, void (*F)(T*)>
struct bar<F>
{
bar(T* t) { F(t); }
};
with usage:
int* p = nullptr;
bar<foo> b(p);
Prior C++17, you might do:
template <typename T, T> struct bar;
template<typename T, void (*F)(T*)>
struct bar<void (*)(T*), F>
{
bar(T* t) { F(t); }
};
With usage:
int* p = nullptr;
bar<decltype(&foo), &foo> b(p);
MACRO can be used to remove duplication such as:
#define BAR(Func) bar<decltype(&Func), &Func>
#define TYPE_AND_VALUE(V) decltype(V), V>
to allow:
BAR(foo) b(p);
bar<TYPE_AND_VALUE(&foo)> b(p);

Calling a templated functor in a class template

Is there any way to call the functor operator()( int ) of a the class template Foo as shown below (online version)
template<typename T>
struct Foo
{
template<typename U>
void operator()( int )
{
}
};
int main(int argc, char *argv[])
{
Foo<char> foo;
foo<bool>( 42 );
}
I'm getting the error message in gcc 4.9.3
error: expected primary-expression before ‘bool’
foo<bool>( 42 );
I'd prepend the functor with template if the member function wasn't a functor and was prefixed with ::, ., or ->. Without some help the compiler couldn't know how to parse this expression ; as a functor or an instantiation of an anonymous object of type foo<int>.
It would work with;
foo.operator()<bool>( 42 );
Operators play best with deduced template argument types.
You don't give enough detail of the context in which this is used, as alternatives you could consider;
making the call operator a member function and thus allow explicit template type arguments
a tag dispatch mechanism
accept the type U as an argument
For example;
template<typename U>
void operator()( int, U&& /*initial*/ )
{
// use the initial value of U
}
// called as...
foo(42, true); // U is bool in your example
Or simply the member function;
template<typename U>
void my_func( int )
{
}
// called as...
foo.my_fun<bool>( 42 );
Yes but it's ugly:
foo.operator()<bool>( 42 );
Unfortunately you'd need to use foo.operator()<bool>(42); for this. foo<bool> is valid for things like C++14 variable templates, not template call operators.
What you could do is tag the type and pass that in as an argument to the call operator to deduce the right type:
//tag
template <typename T>
struct type{};
template<typename T>
struct Foo
{
template<typename U>
//deduction on the tagged type
void operator()( type<U>, int )
{
}
};
int main(int argc, char *argv[])
{
Foo<char> foo;
foo( type<bool>{}, 42 );
// ^^^^^^^^^^^^ pass tag
}
You could make this a bit nicer using C++14 variable templates for the tag:
template <typename T>
struct type_t{};
//variable template for nicer usage
template <typename T>
type_t<T> type;
template<typename T>
struct Foo
{
template<typename U>
void operator()( type_t<U>, int )
{
}
};
int main(int argc, char *argv[])
{
Foo<char> foo;
foo( type<bool>, 42 );
//don't need {}^
}
Sadly the syntax gets more elaborate if the functor is itself a template. The below will fail:
template <typename Functor, typename ... Args>
void Foo (Functor & f)
{
f.operator()<Args...>();
}
struct MyFunctor
{
template <typename ...>
void operator () () {}
};
int main ()
{
MyFunctor f;
Foo(f);
}
We instead must write:
f.template operator()<Args...>();

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"});