Related
Given two or more example functions, is it possible to write templated code which would be able to deduce the arguments of a function provided as a template parameter?
This is the motivating example:
void do_something(int value, double amount) {
std::cout << (value * amount) << std::endl;
}
void do_something_else(std::string const& first, double & second, int third) {
for(char c : first)
if(third / c == 0)
second += 13.7;
}
template<void(*Func)(/*???*/)>
struct wrapper {
using Args = /*???*/;
void operator()(Args&& ... args) const {
Func(std::forward<Args>(args)...);
}
};
int main() {
wrapper<do_something> obj; //Should be able to deduce Args to be [int, double]
obj(5, 17.4); //Would call do_something(5, 17.4);
wrapper<do_something_else> obj2; //Should be able to deduce Args to be [std::string const&, double&, int]
double value = 5;
obj2("Hello there!", value, 70); //Would call do_something_else("Hello there!", value, 70);
}
In both uses of /*???*/, I am trying to work out what I could put there that would enable this kind of code.
The following doesn't appear to work, due to Args not being defined before its first use (along with what I have to assume are numerous syntax errors besides), and even if it did, I'm still looking for a version that doesn't require explicit writing of the types themselves:
template<void(*Func)(Args ...), typename ... Args)
struct wrapper {
void operator()(Args ...args) const {
Func(std::forward<Args>(args)...);
}
};
wrapper<do_something, int, double> obj;
With C++17 we can have auto template non-type parameters which make possible the Wrapper<do_something> w{} syntax 1).
As for deducing Args... you can do that with a specialization.
template <auto* F>
struct Wrapper {};
template <class Ret, class... Args, auto (*F)(Args...) -> Ret>
struct Wrapper<F>
{
auto operator()(Args... args) const
{
return F(args...);
}
};
Wrapper<do_something> w{};
w(10, 11.11);
1) Without C++17 it's impossible to have the Wrapper<do_something> w{} nice syntax.
The best you can do is:
template <class F, F* func>
struct Wrapper {};
template <class Ret, class... Args, auto (*F)(Args...) -> Ret>
struct Wrapper<Ret (Args...), F>
{
auto operator()(Args... args) const
{
return F(args...);
}
};
Wrapper<declype(do_something), do_something> w{};
With C++17, you can do this:
template <auto FUNC, typename = decltype(FUNC)>
struct wrapper;
template <auto FUNC, typename RETURN, typename ...ARGS>
struct wrapper<FUNC, RETURN (*)(ARGS...)> {
RETURN operator()(ARGS ...args) {
return FUNC(args...);
}
};
I've learned this technique from W.F.'s answer
Further improvement of C++17 version: less template parameters and proper noexcept annotation:
template<auto VFnPtr> struct
wrapper;
template<typename TResult, typename... TArgs, TResult ( * VFnPtr)(TArgs...)> struct
wrapper<VFnPtr>
{
TResult
operator ()(TArgs... args) const noexcept(noexcept((*VFnPtr)(::std::forward<TArgs>(args)...)))
{
return (*VFnPtr)(::std::forward<TArgs>(args)...);
}
};
With C++11 you can consider a templated make_wrapper helper function. However, with this approach the function pointer is not a template parameter. Instead, the function pointer is "carried" by the non-static data member called f_ in the following example:
#include <iostream>
void do_something(int value, double amount) {
std::cout << (value * amount) << std::endl;
}
void do_something_else(std::string const& first, double & second, int third) {
for(char c : first)
if(third / c == 0)
second += 13.7;
}
template<class Ret, class... Args>
using function_pointer = Ret(*)(Args...);
template<class Ret, class... Args>
struct wrapper {
using F = function_pointer<Ret, Args...>;
F f_;
explicit constexpr wrapper(F f) noexcept : f_{f} {}
template<class... PreciseArgs>// not sure if this is required
Ret operator()(PreciseArgs&&... precise_args) const {
return f_(std::forward<PreciseArgs>(precise_args)...);
}
};
template<class Ret, class... Args>
constexpr auto make_wrapper(
function_pointer<Ret, Args...> f
) -> wrapper<Ret, Args...> {
return wrapper<Ret, Args...>(f);
}
int main() {
constexpr auto obj = make_wrapper(do_something);
obj(5, 17.4);
constexpr auto obj2 = make_wrapper(do_something_else);
double value = 5;
obj2("Hello there!", value, 70);
return 0;
}
I am trying to write code to do something similar (code written for demonstration purposes) to this:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo([func](Args... args) -> std::result_of<F>::type
{
// Do something before calling func
func(args...);
// Do something after call func
});
}
So basically I am trying to write a function that returns an object that takes lambda that matches the templated function type. Obviously this code won't work because I do not have Args... defined. How would I solve this in C++11?
template<class F_before, class F, class F_after>
struct decorate_func_t {
F_before f0;
F f1;
F_after f2;
template<class...Args>
typename std::result_of<F(Args...)>::type operator()(Args&&...args)const{
f0();
auto r = f1(std::forward<Args>(args)...);
f2();
return r;
}
};
template<class F_before, class F, class F_after>
decorate_func_t<F_before, F, F_after>
decorate_func( F_before before, F f, F_after after ){
return {std::move(before), std::move(f), std::move(after)};
}
Then:
template <typename F, typename Args...>
inline auto runFunc(F func) -> foo
{
return foo(decorate_func(
[]{/* Do something before calling func */},
func,
[]{/* Do something after call func */ }
};
}
the lack of auto parameters in C++11 lambdas makes this about the best you can do.
In C++14 this is trivial:
template <class F>
auto runFunc(F func)
{
return foo(
[func](auto&&... args) // ->decltype(auto) maybe
{
// Do something before calling func
auto r = func(decltype(args)(args)...);
// Do something after call func
return r;
}
);
}
note that many nominally C++11 compilers actually support auto parameters on lambdas.
You can use a support structure as in the following example:
#include<type_traits>
#include<cassert>
struct foo {
template<typename F>
foo(F f) { assert(42 == f(42)); }
};
template<typename>
struct S;
template<typename R, typename... Args>
struct S<R(*)(Args...)> {
template <typename F>
static auto runFunc(F func) -> foo
{
return foo{[func](Args... args) -> R
{
// Do something before calling func
auto r = func(args...);
// Do something after call func
return r;
}};
}
};
template<typename F>
inline auto runFunc(F func) -> foo
{
return S<F>::runFunc(func);
}
int f(int i) { return i; }
int main() {
runFunc(f);
}
For it's not clear to me what's the context of the problem, I'm not sure I got exactly what you were asking for.
I hope the code above can help you.
Still being unsure it this is what you're searching for, I risk posting:
#include <iostream>
struct foo
{
template<typename T>
foo(T lambda)
{
lambda(1, 2);
}
};
template <typename F, typename... Args>
inline typename std::result_of<F>::type runFunc(F func)
{
return foo(
[func](Args... args)
{
std::cout << "Before";
func(args...);
std::cout << "After";
}
);
}
struct print
{
void operator()(int i) const
{
std::cout << i << std::endl;
}
void operator()(int i, int j) const
{
std::cout << i << " " << j << std::endl;
}
};
int main()
{
runFunc<print, int, int>(print());
}
I'm trying to store in a std::tuple a varying number of values, which will later be used as arguments for a call to a function pointer which matches the stored types.
I've created a simplified example showing the problem I'm struggling to solve:
#include <iostream>
#include <tuple>
void f(int a, double b, void* c) {
std::cout << a << ":" << b << ":" << c << std::endl;
}
template <typename ...Args>
struct save_it_for_later {
std::tuple<Args...> params;
void (*func)(Args...);
void delayed_dispatch() {
// How can I "unpack" params to call func?
func(std::get<0>(params), std::get<1>(params), std::get<2>(params));
// But I *really* don't want to write 20 versions of dispatch so I'd rather
// write something like:
func(params...); // Not legal
}
};
int main() {
int a=666;
double b = -1.234;
void *c = NULL;
save_it_for_later<int,double,void*> saved = {
std::tuple<int,double,void*>(a,b,c), f};
saved.delayed_dispatch();
}
Normally for problems involving std::tuple or variadic templates I'd write another template like template <typename Head, typename ...Tail> to recursively evaluate all of the types one by one, but I can't see a way of doing that for dispatching a function call.
The real motivation for this is somewhat more complex and it's mostly just a learning exercise anyway. You can assume that I'm handed the tuple by contract from another interface, so can't be changed but that the desire to unpack it into a function call is mine. This rules out using std::bind as a cheap way to sidestep the underlying problem.
What's a clean way of dispatching the call using the std::tuple, or an alternative better way of achieving the same net result of storing/forwarding some values and a function pointer until an arbitrary future point?
You need to build a parameter pack of numbers and unpack them
template<int ...>
struct seq { };
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> { };
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
// ...
void delayed_dispatch() {
callFunc(typename gens<sizeof...(Args)>::type());
}
template<int ...S>
void callFunc(seq<S...>) {
func(std::get<S>(params) ...);
}
// ...
The C++17 solution is simply to use std::apply:
auto f = [](int a, double b, std::string c) { std::cout<<a<<" "<<b<<" "<<c<< std::endl; };
auto params = std::make_tuple(1,2.0,"Hello");
std::apply(f, params);
Just felt that should be stated once in an answer in this thread (after it already appeared in one of the comments).
The basic C++14 solution is still missing in this thread. EDIT: No, it's actually there in the answer of Walter.
This function is given:
void f(int a, double b, void* c)
{
std::cout << a << ":" << b << ":" << c << std::endl;
}
Call it with the following snippet:
template<typename Function, typename Tuple, size_t ... I>
auto call(Function f, Tuple t, std::index_sequence<I ...>)
{
return f(std::get<I>(t) ...);
}
template<typename Function, typename Tuple>
auto call(Function f, Tuple t)
{
static constexpr auto size = std::tuple_size<Tuple>::value;
return call(f, t, std::make_index_sequence<size>{});
}
Example:
int main()
{
std::tuple<int, double, int*> t;
//or std::array<int, 3> t;
//or std::pair<int, double> t;
call(f, t);
}
DEMO
This is a complete compilable version of Johannes' solution to awoodland's question, in the hope it may be useful to somebody. This was tested with a snapshot of g++ 4.7 on Debian squeeze.
###################
johannes.cc
###################
#include <tuple>
#include <iostream>
using std::cout;
using std::endl;
template<int ...> struct seq {};
template<int N, int ...S> struct gens : gens<N-1, N-1, S...> {};
template<int ...S> struct gens<0, S...>{ typedef seq<S...> type; };
double foo(int x, float y, double z)
{
return x + y + z;
}
template <typename ...Args>
struct save_it_for_later
{
std::tuple<Args...> params;
double (*func)(Args...);
double delayed_dispatch()
{
return callFunc(typename gens<sizeof...(Args)>::type());
}
template<int ...S>
double callFunc(seq<S...>)
{
return func(std::get<S>(params) ...);
}
};
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
int main(void)
{
gens<10> g;
gens<10>::type s;
std::tuple<int, float, double> t = std::make_tuple(1, 1.2, 5);
save_it_for_later<int,float, double> saved = {t, foo};
cout << saved.delayed_dispatch() << endl;
}
#pragma GCC diagnostic pop
One can use the following SConstruct file
#####################
SConstruct
#####################
#!/usr/bin/python
env = Environment(CXX="g++-4.7", CXXFLAGS="-Wall -Werror -g -O3 -std=c++11")
env.Program(target="johannes", source=["johannes.cc"])
On my machine, this gives
g++-4.7 -o johannes.o -c -Wall -Werror -g -O3 -std=c++11 johannes.cc
g++-4.7 -o johannes johannes.o
Here is a C++14 solution.
template <typename ...Args>
struct save_it_for_later
{
std::tuple<Args...> params;
void (*func)(Args...);
template<std::size_t ...I>
void call_func(std::index_sequence<I...>)
{ func(std::get<I>(params)...); }
void delayed_dispatch()
{ call_func(std::index_sequence_for<Args...>{}); }
};
This still needs one helper function (call_func). Since this is a common idiom, perhaps the standard should support it directly as std::call with possible implementation
// helper class
template<typename R, template<typename...> class Params, typename... Args, std::size_t... I>
R call_helper(std::function<R(Args...)> const&func, Params<Args...> const¶ms, std::index_sequence<I...>)
{ return func(std::get<I>(params)...); }
// "return func(params...)"
template<typename R, template<typename...> class Params, typename... Args>
R call(std::function<R(Args...)> const&func, Params<Args...> const¶ms)
{ return call_helper(func,params,std::index_sequence_for<Args...>{}); }
Then our delayed dispatch becomes
template <typename ...Args>
struct save_it_for_later
{
std::tuple<Args...> params;
std::function<void(Args...)> func;
void delayed_dispatch()
{ std::call(func,params); }
};
This is a bit complicated to achieve (even though it is possible). I advise you to use a library where this is already implemented, namely Boost.Fusion (the invoke function). As a bonus, Boost Fusion works with C++03 compilers as well.
c++14 solution. First, some utility boilerplate:
template<std::size_t...Is>
auto index_over(std::index_sequence<Is...>){
return [](auto&&f)->decltype(auto){
return decltype(f)(f)( std::integral_constant<std::size_t, Is>{}... );
};
}
template<std::size_t N>
auto index_upto(std::integral_constant<std::size_t, N> ={}){
return index_over( std::make_index_sequence<N>{} );
}
These let you call a lambda with a series of compile-time integers.
void delayed_dispatch() {
auto indexer = index_upto<sizeof...(Args)>();
indexer([&](auto...Is){
func(std::get<Is>(params)...);
});
}
and we are done.
index_upto and index_over let you work with parameter packs without having to generate a new external overloads.
Of course, in c++17 you just
void delayed_dispatch() {
std::apply( func, params );
}
Now, if we like that, in c++14 we can write:
namespace notstd {
template<class T>
constexpr auto tuple_size_v = std::tuple_size<T>::value;
template<class F, class Tuple>
decltype(auto) apply( F&& f, Tuple&& tup ) {
auto indexer = index_upto<
tuple_size_v<std::remove_reference_t<Tuple>>
>();
return indexer(
[&](auto...Is)->decltype(auto) {
return std::forward<F>(f)(
std::get<Is>(std::forward<Tuple>(tup))...
);
}
);
}
}
relatively easily and get the cleaner c++17 syntax ready to ship.
void delayed_dispatch() {
notstd::apply( func, params );
}
just replace notstd with std when your compiler upgrades and bob is your uncle.
Thinking about the problem some more based on the answer given I've found another way of solving the same problem:
template <int N, int M, typename D>
struct call_or_recurse;
template <typename ...Types>
struct dispatcher {
template <typename F, typename ...Args>
static void impl(F f, const std::tuple<Types...>& params, Args... args) {
call_or_recurse<sizeof...(Args), sizeof...(Types), dispatcher<Types...> >::call(f, params, args...);
}
};
template <int N, int M, typename D>
struct call_or_recurse {
// recurse again
template <typename F, typename T, typename ...Args>
static void call(F f, const T& t, Args... args) {
D::template impl(f, t, std::get<M-(N+1)>(t), args...);
}
};
template <int N, typename D>
struct call_or_recurse<N,N,D> {
// do the call
template <typename F, typename T, typename ...Args>
static void call(F f, const T&, Args... args) {
f(args...);
}
};
Which requires changing the implementation of delayed_dispatch() to:
void delayed_dispatch() {
dispatcher<Args...>::impl(func, params);
}
This works by recursively converting the std::tuple into a parameter pack in its own right. call_or_recurse is needed as a specialization to terminate the recursion with the real call, which just unpacks the completed parameter pack.
I'm not sure this is in anyway a "better" solution, but it's another way of thinking about and solving it.
As another alternative solution you can use enable_if, to form something arguably simpler than my previous solution:
#include <iostream>
#include <functional>
#include <tuple>
void f(int a, double b, void* c) {
std::cout << a << ":" << b << ":" << c << std::endl;
}
template <typename ...Args>
struct save_it_for_later {
std::tuple<Args...> params;
void (*func)(Args...);
template <typename ...Actual>
typename std::enable_if<sizeof...(Actual) != sizeof...(Args)>::type
delayed_dispatch(Actual&& ...a) {
delayed_dispatch(std::forward<Actual>(a)..., std::get<sizeof...(Actual)>(params));
}
void delayed_dispatch(Args ...args) {
func(args...);
}
};
int main() {
int a=666;
double b = -1.234;
void *c = NULL;
save_it_for_later<int,double,void*> saved = {
std::tuple<int,double,void*>(a,b,c), f};
saved.delayed_dispatch();
}
The first overload just takes one more argument from the tuple and puts it into a parameter pack. The second overload takes a matching parameter pack and then makes the real call, with the first overload being disabled in the one and only case where the second would be viable.
My variation of the solution from Johannes using the C++14 std::index_sequence (and function return type as template parameter RetT):
template <typename RetT, typename ...Args>
struct save_it_for_later
{
RetT (*func)(Args...);
std::tuple<Args...> params;
save_it_for_later(RetT (*f)(Args...), std::tuple<Args...> par) : func { f }, params { par } {}
RetT delayed_dispatch()
{
return callFunc(std::index_sequence_for<Args...>{});
}
template<std::size_t... Is>
RetT callFunc(std::index_sequence<Is...>)
{
return func(std::get<Is>(params) ...);
}
};
double foo(int x, float y, double z)
{
return x + y + z;
}
int testTuple(void)
{
std::tuple<int, float, double> t = std::make_tuple(1, 1.2, 5);
save_it_for_later<double, int, float, double> saved (&foo, t);
cout << saved.delayed_dispatch() << endl;
return 0;
}
a lot of answers have been provided but I found them too complicated and not very natural. I did it another way, without using sizeof or counters.
I used my own simple structure (ParameterPack) for parameters to access the tail of parameters instead of a tuple. Then, I appended all the parameters from my structure into function parameters, and finnally, when no more parameters were to be unpacked, I run the function.
Here is the code in C++11, I agree that there is more code than in others answers, but I found it more understandable.
template <class ...Args>
struct PackParameters;
template <>
struct PackParameters <>
{
PackParameters() = default;
};
template <class T, class ...Args>
struct PackParameters <T, Args...>
{
PackParameters ( T firstElem, Args... args ) : value ( firstElem ),
rest ( args... ) {}
T value;
PackParameters<Args...> rest;
};
template <class ...Args>
struct RunFunction;
template <class T, class ...Args>
struct RunFunction<T, Args...>
{
template <class Function>
static void Run ( Function f, const PackParameters<T, Args...>& args );
template <class Function, class... AccumulatedArgs>
static void RunChild (
Function f,
const PackParameters<T, Args...>& remainingParams,
AccumulatedArgs... args
);
};
template <class T, class ...Args>
template <class Function>
void RunFunction<T, Args...>::Run (
Function f,
const PackParameters<T, Args...>& remainingParams
)
{
RunFunction<Args...>::template RunChild ( f, remainingParams.rest,
remainingParams.value );
}
template <class T, class ...Args>
template<class Function, class ...AccumulatedArgs>
void RunFunction<T, Args...>::RunChild ( Function f,
const PackParameters<T, Args...>& remainingParams,
AccumulatedArgs... args )
{
RunFunction<Args...>:: template RunChild ( f, remainingParams.rest,
args..., remainingParams.value );
}
template <>
struct RunFunction<>
{
template <class Function, class... AccumulatedArgs>
static void RunChild ( Function f, PackParameters<>, AccumulatedArgs... args )
{
f ( args... );
}
template <class Function>
static void Run ( Function f, PackParameters<> )
{
f ();
}
};
struct Toto
{
std::string k = "I am toto";
};
void f ( int i, Toto t, float b, std::string introMessage )
{
float res = i * b;
std::cerr << introMessage << " " << res << std::endl;
std::cerr << "Toto " << t.k << std::endl;
}
int main(){
Toto t;
PackParameters<int, Toto, float, std::string> pack ( 3, t, 4.0, " 3 * 4 =" );
RunFunction<int, Toto, float, std::string>::Run ( f, pack );
return 0;
}
I'm trying to create a function which can be called with a lambda that takes either 0, 1 or 2 arguments. Since I need the code to work on both g++ 4.5 and vs2010(which doesn't support variadic templates or lambda conversions to function pointers) the only idea I've come up with is to choose which implementation to call based on arity. The below is my non working guess at how this should look. Is there any way to fix my code or is there a better way to do this in general?
#include <iostream>
#include <functional>
using namespace std;
template <class Func> struct arity;
template <class Func>
struct arity<Func()>{ static const int val = 0; };
template <class Func, class Arg1>
struct arity<Func(Arg1)>{ static const int val = 1; };
template <class Func, class Arg1, class Arg2>
struct arity<Func(Arg1,Arg2)>{ static const int val = 2; };
template<class F>
void bar(F f)
{
cout << arity<F>::val << endl;
}
int main()
{
bar([]{cout << "test" << endl;});
}
A lambda function is a class type with a single function call operator. You can thus detect the arity of that function call operator by taking its address and using overload resolution to select which function to call:
#include <iostream>
template<typename F,typename R>
void do_stuff(F& f,R (F::*mf)() const)
{
(f.*mf)();
}
template<typename F,typename R,typename A1>
void do_stuff(F& f,R (F::*mf)(A1) const)
{
(f.*mf)(99);
}
template<typename F,typename R,typename A1,typename A2>
void do_stuff(F& f,R (F::*mf)(A1,A2) const)
{
(f.*mf)(42,123);
}
template<typename F>
void do_stuff(F f)
{
do_stuff(f,&F::operator());
}
int main()
{
do_stuff([]{std::cout<<"no args"<<std::endl;});
do_stuff([](int a1){std::cout<<"1 args="<<a1<<std::endl;});
do_stuff([](int a1,int a2){std::cout<<"2 args="<<a1<<","<<a2<<std::endl;});
}
Be careful though: this won't work with function types, or class types that have more than one function call operator, or non-const function call operators.
I thought the following would work but it doesn't, I'm posting it for two reasons.
To save people the time if they had the same idea
If someone knows why this doesn't work, I'm not 100% sure I understand (although I have my suspicions)
Code follows:
#include <iostream>
#include <functional>
template <typename Ret>
unsigned arity(std::function<Ret()>) { return 0; }
template <typename Ret, typename A1>
unsigned arity(std::function<Ret(A1)>) { return 1; }
template <typename Ret, typename A1, typename A2>
unsigned arity(std::function<Ret(A1, A2)>) { return 2; }
// rinse and repeat
int main()
{
std::function<void(int)> f = [](int i) { }; // this binds fine
// Error: no matching function for call to 'arity(main()::<lambda(int)>)'
std::cout << arity([](int i) { });
}
Compile time means of obtaining the arity of a function or a function object, including that of a lambda:
int main (int argc, char ** argv) {
auto f0 = []() {};
auto f1 = [](int) {};
auto f2 = [](int, void *) {};
std::cout << Arity<decltype(f0)>::value << std::endl; // 0
std::cout << Arity<decltype(f1)>::value << std::endl; // 1
std::cout << Arity<decltype(f2)>::value << std::endl; // 2
std::cout << Arity<decltype(main)>::value << std::endl; // 2
}
template <typename Func>
class Arity {
private:
struct Any {
template <typename T>
operator T ();
};
template <typename T>
struct Id {
typedef T type;
};
template <size_t N>
struct Size {
enum { value = N };
};
template <typename F>
static Size<0> match (
F f,
decltype(f()) * = nullptr);
template <typename F>
static Size<1> match (
F f,
decltype(f(Any())) * = nullptr,
decltype(f(Any())) * = nullptr);
template <typename F>
static Size<2> match (
F f,
decltype(f(Any(), Any())) * = nullptr,
decltype(f(Any(), Any())) * = nullptr,
decltype(f(Any(), Any())) * = nullptr);
public:
enum { value = Id<decltype(match(static_cast<Func>(Any())))>::type::value };
};
This way works:
template<typename F>
auto call(F f) -> decltype(f(1))
{
return f(1);
}
template<typename F>
auto call(F f, void * fake = 0) -> decltype(f(2,3))
{
return f(2,3);
}
template<typename F>
auto call(F f, void * fake = 0, void * fake2 = 0) -> decltype(f(4,5,6))
{
return f(4,5,6);
}
int main()
{
auto x1 = call([](int a){ return a*10; });
auto x2 = call([](int a, int b){ return a*b; });
auto x3 = call([](int a, int b, int c){ return a*b*c; });
// x1 == 1*10
// x2 == 2*3
// x3 == 4*5*6
}
It works for all callable types (lambdas, functors, etc)
What is currying?
How can currying be done in C++?
Please Explain binders in STL container?
1. What is currying?
Currying simply means a transformation of a function of several arguments to a function of a single argument. This is most easily illustrated using an example:
Take a function f that accepts three arguments:
int
f(int a,std::string b,float c)
{
// do something with a, b, and c
return 0;
}
If we want to call f, we have to provide all of its arguments f(1,"some string",19.7f).
Then a curried version of f, let's call it curried_f=curry(f) only expects a single argument, that corresponds to the first argument of f, namely the argument a. Additionally, f(1,"some string",19.7f) can also be written using the curried version as curried_f(1)("some string")(19.7f). The return value of curried_f(1) on the other hand is just another function, that handles the next argument of f. In the end, we end up with a function or callable curried_f that fulfills the following equality:
curried_f(first_arg)(second_arg)...(last_arg) == f(first_arg,second_arg,...,last_arg).
2. How can currying be achieved in C++?
The following is a little bit more complicated, but works very well for me (using c++11)... It also allows currying of arbitrary degree like so: auto curried=curry(f)(arg1)(arg2)(arg3) and later auto result=curried(arg4)(arg5). Here it goes:
#include <functional>
namespace _dtl {
template <typename FUNCTION> struct
_curry;
// specialization for functions with a single argument
template <typename R,typename T> struct
_curry<std::function<R(T)>> {
using
type = std::function<R(T)>;
const type
result;
_curry(type fun) : result(fun) {}
};
// recursive specialization for functions with more arguments
template <typename R,typename T,typename...Ts> struct
_curry<std::function<R(T,Ts...)>> {
using
remaining_type = typename _curry<std::function<R(Ts...)> >::type;
using
type = std::function<remaining_type(T)>;
const type
result;
_curry(std::function<R(T,Ts...)> fun)
: result (
[=](const T& t) {
return _curry<std::function<R(Ts...)>>(
[=](const Ts&...ts){
return fun(t, ts...);
}
).result;
}
) {}
};
}
template <typename R,typename...Ts> auto
curry(const std::function<R(Ts...)> fun)
-> typename _dtl::_curry<std::function<R(Ts...)>>::type
{
return _dtl::_curry<std::function<R(Ts...)>>(fun).result;
}
template <typename R,typename...Ts> auto
curry(R(* const fun)(Ts...))
-> typename _dtl::_curry<std::function<R(Ts...)>>::type
{
return _dtl::_curry<std::function<R(Ts...)>>(fun).result;
}
#include <iostream>
void
f(std::string a,std::string b,std::string c)
{
std::cout << a << b << c;
}
int
main() {
curry(f)("Hello ")("functional ")("world!");
return 0;
}
View output
OK, as Samer commented, I should add some explanations as to how this works. The actual implementation is done in the _dtl::_curry, while the template functions curry are only convenience wrappers. The implementation is recursive over the arguments of the std::function template argument FUNCTION.
For a function with only a single argument, the result is identical to the original function.
_curry(std::function<R(T,Ts...)> fun)
: result (
[=](const T& t) {
return _curry<std::function<R(Ts...)>>(
[=](const Ts&...ts){
return fun(t, ts...);
}
).result;
}
) {}
Here the tricky thing: For a function with more arguments, we return a lambda whose argument is bound to the first argument to the call to fun. Finally, the remaining currying for the remaining N-1 arguments is delegated to the implementation of _curry<Ts...> with one less template argument.
Update for c++14 / 17:
A new idea to approach the problem of currying just came to me... With the introduction of if constexpr into c++17 (and with the help of void_t to determine if a function is fully curried), things seem to get a lot easier:
template< class, class = std::void_t<> > struct
needs_unapply : std::true_type { };
template< class T > struct
needs_unapply<T, std::void_t<decltype(std::declval<T>()())>> : std::false_type { };
template <typename F> auto
curry(F&& f) {
/// Check if f() is a valid function call. If not we need
/// to curry at least one argument:
if constexpr (needs_unapply<decltype(f)>::value) {
return [=](auto&& x) {
return curry(
[=](auto&&...xs) -> decltype(f(x,xs...)) {
return f(x,xs...);
}
);
};
}
else {
/// If 'f()' is a valid call, just call it, we are done.
return f();
}
}
int
main()
{
auto f = [](auto a, auto b, auto c, auto d) {
return a * b * c * d;
};
return curry(f)(1)(2)(3)(4);
}
See code in action on here. With a similar approach, here is how to curry functions with arbitrary number of arguments.
The same idea seems to work out also in C++14, if we exchange the constexpr if with a template selection depending on the test needs_unapply<decltype(f)>::value:
template <typename F> auto
curry(F&& f);
template <bool> struct
curry_on;
template <> struct
curry_on<false> {
template <typename F> static auto
apply(F&& f) {
return f();
}
};
template <> struct
curry_on<true> {
template <typename F> static auto
apply(F&& f) {
return [=](auto&& x) {
return curry(
[=](auto&&...xs) -> decltype(f(x,xs...)) {
return f(x,xs...);
}
);
};
}
};
template <typename F> auto
curry(F&& f) {
return curry_on<needs_unapply<decltype(f)>::value>::template apply(f);
}
In short, currying takes a function f(x, y) and given a fixed Y, gives a new function g(x) where
g(x) == f(x, Y)
This new function may be called in situations where only one argument is supplied, and passes the call on to the original f function with the fixed Y argument.
The binders in the STL allow you to do this for C++ functions. For example:
#include <functional>
#include <iostream>
#include <vector>
using namespace std;
// declare a binary function object
class adder: public binary_function<int, int, int> {
public:
int operator()(int x, int y) const
{
return x + y;
}
};
int main()
{
// initialise some sample data
vector<int> a, b;
a.push_back(1);
a.push_back(2);
a.push_back(3);
// here we declare a function object f and try it out
adder f;
cout << "f(2, 3) = " << f(2, 3) << endl;
// transform() expects a function with one argument, so we use
// bind2nd to make a new function based on f, that takes one
// argument and adds 5 to it
transform(a.begin(), a.end(), back_inserter(b), bind2nd(f, 5));
// output b to see what we got
cout << "b = [" << endl;
for (vector<int>::iterator i = b.begin(); i != b.end(); ++i) {
cout << " " << *i << endl;
}
cout << "]" << endl;
return 0;
}
Simplifying Gregg's example, using tr1:
#include <functional>
using namespace std;
using namespace std::tr1;
using namespace std::tr1::placeholders;
int f(int, int);
..
int main(){
function<int(int)> g = bind(f, _1, 5); // g(x) == f(x, 5)
function<int(int)> h = bind(f, 2, _1); // h(x) == f(2, x)
function<int(int,int)> j = bind(g, _2); // j(x,y) == g(y)
}
Tr1 functional components allow you to write rich functional-style code in C++. As well, C++0x will allow for in-line lambda functions to do this as well:
int f(int, int);
..
int main(){
auto g = [](int x){ return f(x,5); }; // g(x) == f(x, 5)
auto h = [](int x){ return f(2,x); }; // h(x) == f(2, x)
auto j = [](int x, int y){ return g(y); }; // j(x,y) == g(y)
}
And while C++ doesn't provide the rich side-effect analysis that some functional-oriented programming languages perform, const analysis and C++0x lambda syntax can help:
struct foo{
int x;
int operator()(int y) const {
x = 42; // error! const function can't modify members
}
};
..
int main(){
int x;
auto f = [](int y){ x = 42; }; // error! lambdas don't capture by default.
}
Hope that helps.
Have a look at Boost.Bind which makes the process shown by Greg more versatile:
transform(a.begin(), a.end(), back_inserter(b), bind(f, _1, 5));
This binds 5 to f's second argument.
It’s worth noting that this is not currying (instead, it’s partial application). However, using currying in a general way is hard in C++ (in fact, it only recently became possible at all) and partial application is often used instead.
Other answers nicely explain binders, so I won't repeat that part here. I will only demonstrate how currying and partial application can be done with lambdas in C++0x.
Code example: (Explanation in comments)
#include <iostream>
#include <functional>
using namespace std;
const function<int(int, int)> & simple_add =
[](int a, int b) -> int {
return a + b;
};
const function<function<int(int)>(int)> & curried_add =
[](int a) -> function<int(int)> {
return [a](int b) -> int {
return a + b;
};
};
int main() {
// Demonstrating simple_add
cout << simple_add(4, 5) << endl; // prints 9
// Demonstrating curried_add
cout << curried_add(4)(5) << endl; // prints 9
// Create a partially applied function from curried_add
const auto & add_4 = curried_add(4);
cout << add_4(5) << endl; // prints 9
}
If you're using C++14 it's very easy:
template<typename Function, typename... Arguments>
auto curry(Function function, Arguments... args) {
return [=](auto... rest) {
return function(args..., rest...);
}; // don't forget semicolumn
}
You can then use it like this:
auto add = [](auto x, auto y) { return x + y; }
// curry 4 into add
auto add4 = curry(add, 4);
add4(6); // 10
Some great answers here. I thought I would add my own because it was fun to play around with the concept.
Partial function application: The process of "binding" a function with only some of its parameters, deferring the rest to be filled in later. The result is another function with fewer parameters.
Currying: Is a special form of partial function application where you can only "bind" a single argument at a time. The result is another function with exactly 1 fewer parameter.
The code I'm about to present is partial function application from which currying is possible, but not the only possibility. It offers a few benefits over the above currying implementations (mainly because it's partial function application and not currying, heh).
Applying over an empty function:
auto sum0 = [](){return 0;};
std::cout << partial_apply(sum0)() << std::endl;
Applying multiple arguments at a time:
auto sum10 = [](int a, int b, int c, int d, int e, int f, int g, int h, int i, int j){return a+b+c+d+e+f+g+h+i+j;};
std::cout << partial_apply(sum10)(1)(1,1)(1,1,1)(1,1,1,1) << std::endl; // 10
constexpr support that allows for compile-time static_assert:
static_assert(partial_apply(sum0)() == 0);
A useful error message if you accidentally go too far in providing arguments:
auto sum1 = [](int x){ return x;};
partial_apply(sum1)(1)(1);
error: static_assert failed "Attempting to apply too many arguments!"
Other answers above return lambdas that bind an argument and then return further lambdas. This approach wraps that essential functionality into a callable object. Definitions for operator() allow the internal lambda to be called. Variadic templates allow us to check for someone going too far, and an implicit conversion function to the result type of the function call allows us to print the result or compare the object to a primitive.
Code:
namespace detail{
template<class F>
using is_zero_callable = decltype(std::declval<F>()());
template<class F>
constexpr bool is_zero_callable_v = std::experimental::is_detected_v<is_zero_callable, F>;
}
template<class F>
struct partial_apply_t
{
template<class... Args>
constexpr auto operator()(Args... args)
{
static_assert(sizeof...(args) == 0 || !is_zero_callable, "Attempting to apply too many arguments!");
auto bind_some = [=](auto... rest) -> decltype(myFun(args..., rest...))
{
return myFun(args..., rest...);
};
using bind_t = decltype(bind_some);
return partial_apply_t<bind_t>{bind_some};
}
explicit constexpr partial_apply_t(F fun) : myFun(fun){}
constexpr operator auto()
{
if constexpr (is_zero_callable)
return myFun();
else
return *this; // a callable
}
static constexpr bool is_zero_callable = detail::is_zero_callable_v<F>;
F myFun;
};
Live Demo
A few more notes:
I chose to use is_detected mainly for enjoyment and practice; it serves the same as a normal type trait would here.
There could definitely be more work done to support perfect forwarding for performance reasons
The code is C++17 because it requires for constexpr lambda support in C++17
And it seems that GCC 7.0.1 is not quite there yet, either, so I used Clang 5.0.0
Some tests:
auto sum0 = [](){return 0;};
auto sum1 = [](int x){ return x;};
auto sum2 = [](int x, int y){ return x + y;};
auto sum3 = [](int x, int y, int z){ return x + y + z; };
auto sum10 = [](int a, int b, int c, int d, int e, int f, int g, int h, int i, int j){return a+b+c+d+e+f+g+h+i+j;};
std::cout << partial_apply(sum0)() << std::endl; //0
static_assert(partial_apply(sum0)() == 0, "sum0 should return 0");
std::cout << partial_apply(sum1)(1) << std::endl; // 1
std::cout << partial_apply(sum2)(1)(1) << std::endl; // 2
std::cout << partial_apply(sum3)(1)(1)(1) << std::endl; // 3
static_assert(partial_apply(sum3)(1)(1)(1) == 3, "sum3 should return 3");
std::cout << partial_apply(sum10)(1)(1,1)(1,1,1)(1,1,1,1) << std::endl; // 10
//partial_apply(sum1)(1)(1); // fails static assert
auto partiallyApplied = partial_apply(sum3)(1)(1);
std::function<int(int)> finish_applying = partiallyApplied;
std::cout << std::boolalpha << (finish_applying(1) == 3) << std::endl; // true
auto plus2 = partial_apply(sum3)(1)(1);
std::cout << std::boolalpha << (plus2(1) == 3) << std::endl; // true
std::cout << std::boolalpha << (plus2(3) == 5) << std::endl; // true
Currying is a way of reducing a function that takes multiple arguments into a sequence of nested functions with one argument each:
full = (lambda a, b, c: (a + b + c))
print full (1, 2, 3) # print 6
# Curried style
curried = (lambda a: (lambda b: (lambda c: (a + b + c))))
print curried (1)(2)(3) # print 6
Currying is nice because you can define functions that are simply wrappers around other functions with pre-defined values, and then pass around the simplified functions. C++ STL binders provide an implementation of this in C++.
I implemented currying with variadic templates as well (see Julian's answer). However, I did not make use of recursion or std::function. Note: It uses a number of C++14 features.
The provided example (main function) actually runs at compile time, proving that the currying method does not trump essential optimizations by the compiler.
The code can be found here: https://gist.github.com/Garciat/c7e4bef299ee5c607948
with this helper file: https://gist.github.com/Garciat/cafe27d04cfdff0e891e
The code still needs (a lot of) work, which I may or may not complete soon. Either way, I'm posting this here for future reference.
Posting code in case links die (though they shouldn't):
#include <type_traits>
#include <tuple>
#include <functional>
#include <iostream>
// ---
template <typename FType>
struct function_traits;
template <typename RType, typename... ArgTypes>
struct function_traits<RType(ArgTypes...)> {
using arity = std::integral_constant<size_t, sizeof...(ArgTypes)>;
using result_type = RType;
template <size_t Index>
using arg_type = typename std::tuple_element<Index, std::tuple<ArgTypes...>>::type;
};
// ---
namespace details {
template <typename T>
struct function_type_impl
: function_type_impl<decltype(&T::operator())>
{ };
template <typename RType, typename... ArgTypes>
struct function_type_impl<RType(ArgTypes...)> {
using type = RType(ArgTypes...);
};
template <typename RType, typename... ArgTypes>
struct function_type_impl<RType(*)(ArgTypes...)> {
using type = RType(ArgTypes...);
};
template <typename RType, typename... ArgTypes>
struct function_type_impl<std::function<RType(ArgTypes...)>> {
using type = RType(ArgTypes...);
};
template <typename T, typename RType, typename... ArgTypes>
struct function_type_impl<RType(T::*)(ArgTypes...)> {
using type = RType(ArgTypes...);
};
template <typename T, typename RType, typename... ArgTypes>
struct function_type_impl<RType(T::*)(ArgTypes...) const> {
using type = RType(ArgTypes...);
};
}
template <typename T>
struct function_type
: details::function_type_impl<typename std::remove_cv<typename std::remove_reference<T>::type>::type>
{ };
// ---
template <typename Args, typename Params>
struct apply_args;
template <typename HeadArgs, typename... Args, typename HeadParams, typename... Params>
struct apply_args<std::tuple<HeadArgs, Args...>, std::tuple<HeadParams, Params...>>
: std::enable_if<
std::is_constructible<HeadParams, HeadArgs>::value,
apply_args<std::tuple<Args...>, std::tuple<Params...>>
>::type
{ };
template <typename... Params>
struct apply_args<std::tuple<>, std::tuple<Params...>> {
using type = std::tuple<Params...>;
};
// ---
template <typename TupleType>
struct is_empty_tuple : std::false_type { };
template <>
struct is_empty_tuple<std::tuple<>> : std::true_type { };
// ----
template <typename FType, typename GivenArgs, typename RestArgs>
struct currying;
template <typename FType, typename... GivenArgs, typename... RestArgs>
struct currying<FType, std::tuple<GivenArgs...>, std::tuple<RestArgs...>> {
std::tuple<GivenArgs...> given_args;
FType func;
template <typename Func, typename... GivenArgsReal>
constexpr
currying(Func&& func, GivenArgsReal&&... args) :
given_args(std::forward<GivenArgsReal>(args)...),
func(std::move(func))
{ }
template <typename... Args>
constexpr
auto operator() (Args&&... args) const& {
using ParamsTuple = std::tuple<RestArgs...>;
using ArgsTuple = std::tuple<Args...>;
using RestArgsPrime = typename apply_args<ArgsTuple, ParamsTuple>::type;
using CanExecute = is_empty_tuple<RestArgsPrime>;
return apply(CanExecute{}, std::make_index_sequence<sizeof...(GivenArgs)>{}, std::forward<Args>(args)...);
}
template <typename... Args>
constexpr
auto operator() (Args&&... args) && {
using ParamsTuple = std::tuple<RestArgs...>;
using ArgsTuple = std::tuple<Args...>;
using RestArgsPrime = typename apply_args<ArgsTuple, ParamsTuple>::type;
using CanExecute = is_empty_tuple<RestArgsPrime>;
return std::move(*this).apply(CanExecute{}, std::make_index_sequence<sizeof...(GivenArgs)>{}, std::forward<Args>(args)...);
}
private:
template <typename... Args, size_t... Indices>
constexpr
auto apply(std::false_type, std::index_sequence<Indices...>, Args&&... args) const& {
using ParamsTuple = std::tuple<RestArgs...>;
using ArgsTuple = std::tuple<Args...>;
using RestArgsPrime = typename apply_args<ArgsTuple, ParamsTuple>::type;
using CurryType = currying<FType, std::tuple<GivenArgs..., Args...>, RestArgsPrime>;
return CurryType{ func, std::get<Indices>(given_args)..., std::forward<Args>(args)... };
}
template <typename... Args, size_t... Indices>
constexpr
auto apply(std::false_type, std::index_sequence<Indices...>, Args&&... args) && {
using ParamsTuple = std::tuple<RestArgs...>;
using ArgsTuple = std::tuple<Args...>;
using RestArgsPrime = typename apply_args<ArgsTuple, ParamsTuple>::type;
using CurryType = currying<FType, std::tuple<GivenArgs..., Args...>, RestArgsPrime>;
return CurryType{ std::move(func), std::get<Indices>(std::move(given_args))..., std::forward<Args>(args)... };
}
template <typename... Args, size_t... Indices>
constexpr
auto apply(std::true_type, std::index_sequence<Indices...>, Args&&... args) const& {
return func(std::get<Indices>(given_args)..., std::forward<Args>(args)...);
}
template <typename... Args, size_t... Indices>
constexpr
auto apply(std::true_type, std::index_sequence<Indices...>, Args&&... args) && {
return func(std::get<Indices>(std::move(given_args))..., std::forward<Args>(args)...);
}
};
// ---
template <typename FType, size_t... Indices>
constexpr
auto curry(FType&& func, std::index_sequence<Indices...>) {
using RealFType = typename function_type<FType>::type;
using FTypeTraits = function_traits<RealFType>;
using CurryType = currying<FType, std::tuple<>, std::tuple<typename FTypeTraits::template arg_type<Indices>...>>;
return CurryType{ std::move(func) };
}
template <typename FType>
constexpr
auto curry(FType&& func) {
using RealFType = typename function_type<FType>::type;
using FTypeArity = typename function_traits<RealFType>::arity;
return curry(std::move(func), std::make_index_sequence<FTypeArity::value>{});
}
// ---
int main() {
auto add = curry([](int a, int b) { return a + b; });
std::cout << add(5)(10) << std::endl;
}
These Links are relevant:
The Lambda Calculus page on Wikipedia has a clear example of currying
http://en.wikipedia.org/wiki/Lambda_calculus#Motivation
This paper treats currying in C/C++
http://asg.unige.ch/site/papers/Dami91a.pdf
C++20 provides bind_front for doing currying.
For older C++ version it can be implemented (for single argument) as follows:
template <typename TFunc, typename TArg>
class CurryT
{
private:
TFunc func;
TArg arg ;
public:
template <typename TFunc_, typename TArg_>
CurryT(TFunc_ &&func, TArg_ &&arg)
: func(std::forward<TFunc_>(func))
, arg (std::forward<TArg_ >(arg ))
{}
template <typename... TArgs>
auto operator()(TArgs &&...args) const
-> decltype( func(arg, std::forward<TArgs>(args)...) )
{ return func(arg, std::forward<TArgs>(args)...); }
};
template <typename TFunc, typename TArg>
CurryT<std::decay_t<TFunc>, std::remove_cv_t<TArg>> Curry(TFunc &&func, TArg &&arg)
{ return {std::forward<TFunc>(func), std::forward<TArg>(arg)}; }
https://coliru.stacked-crooked.com/a/82856e39da5fa50d
void Abc(std::string a, int b, int c)
{
std::cerr << a << b << c << std::endl;
}
int main()
{
std::string str = "Hey";
auto c1 = Curry(Abc, str);
std::cerr << "str: " << str << std::endl;
c1(1, 2);
auto c2 = Curry(std::move(c1), 3);
c2(4);
auto c3 = Curry(c2, 5);
c3();
}
Output:
str:
Hey12
Hey34
Hey35
If you use long chains of currying then std::shared_ptr optimization can be used to avoid copying all previous curried parameters to each new carried function.
template <typename TFunc>
class SharedFunc
{
public:
struct Tag{}; // For avoiding shadowing copy/move constructors with the
// templated constructor below which accepts any parameters.
template <typename... TArgs>
SharedFunc(Tag, TArgs &&...args)
: p_func( std::make_shared<TFunc>(std::forward<TArgs>(args)...) )
{}
template <typename... TArgs>
auto operator()(TArgs &&...args) const
-> decltype( (*p_func)(std::forward<TArgs>(args)...) )
{ return (*p_func)(std::forward<TArgs>(args)...); }
private:
std::shared_ptr<TFunc> p_func;
};
template <typename TFunc, typename TArg>
SharedFunc<
CurryT<std::decay_t<TFunc>, std::remove_cv_t<TArg>>
>
CurryShared(TFunc &&func, TArg &&arg)
{
return { {}, std::forward<TFunc>(func), std::forward<TArg>(arg) };
}
https://coliru.stacked-crooked.com/a/6e71f41e1cc5fd5c