Function composition from std::vector<std::function> - c++

Expanding on #nes code (https://codereview.stackexchange.com/questions/67241/function-composition-using-stdbind), is there a way to edit the code, so that the input to make_composition_function could be a vector of functions instead of functions as separate arguments.
#include <iostream>
#include <functional>
#include <vector>
// traits to infer the return type of recursive binds
template<typename... Fn>
struct composite_function_traits;
// bind a single function with a placeholder
template<typename F1>
struct composite_function_traits<F1> { typedef decltype(std::bind(std::declval<F1>(), std::placeholders::_1)) type; };
template<typename F1>
typename composite_function_traits<F1>::type make_composite_function(F1&& f1)
{
return std::bind(std::forward<F1>(f1), std::placeholders::_1);
}
// recursively bind multiple functions
template<typename F1, typename... Fn>
struct composite_function_traits<F1, Fn...> { typedef decltype(std::bind(std::declval<F1>(), std::declval<typename composite_function_traits<Fn...>::type>())) type; };
template<typename F1, typename... Fn>
typename composite_function_traits<F1, Fn...>::type make_composite_function(F1&& f1, Fn&&... fn)
{
return std::bind(std::forward<F1>(f1), make_composite_function(std::forward<Fn>(fn)...));
}
int main() {
using namespace std;
auto f1 = [] (int x) { cout << "f1" << endl; return x; };
auto f2 = [] (int x) { cout << "f2" << endl; return x; };
auto f3 = [] (int x) { cout << "f3" << endl; return x; };
// this works -> int y = make_composite_function(f1, f2, f3)(1);
// what I would like to be able to do
std::vector<std::function<int(int)>> funvec;
funvec.push_back(f1);
funvec.push_back(f2);
funvec.push_back(f3);
int y = make_composite_function(funvec)(1);
// print result
cout << y << endl;
}

You might do something like:
template <typename T>
std::function<T(T)> make_composite_function(std::vector<std::function<T(T)>> v)
{
std::reverse(v.begin(), v.end());
return [=](T t) {
for (const auto& f : v) {
t = f(t);
}
return t;
};
}
Demo
You don't even have to use SFINAE for previous overloads by passing vector by value.

Related

Convert overloaded functions to specialized function templates

I've a function that is currently overloaded for different data types and takes a lambda(function pointer) to initialize those data types. I'm in process of converting them to template instances but haven't been successful yet.
Here's the overloaded version -
#include <iostream>
using namespace std;
void doSome(int (*func)(int &)){
int a;
a = 5;
int res = func(a);
cout << a << "\n";
}
void doSome(int (*func)(double &)){
double a;
a = 5.2;
int res = func(a);
cout << a << "\n";
}
int main() {
doSome([](int &a){
a += 2;
return 1;
});
doSome([](double &a){
a += 2.5;
return 1;
});
return 0;
}
Note that I've taken example of int and double for simplification, they might be some entirely different(and complex) types in actual code.
Here's what I've tried yet -
#include <iostream>
using namespace std;
template <typename F, typename S>
void doSome(F &func){
S a;
auto res = func(a);
cout << res << "\n";
}
template<>
void doSome<typename F, int> (F &func){
int a;
a = 5;
auto res = func(a);
cout << res << "\n";
}
template<>
void dpSome<typename F, double> (F &func){
double a;
a = 5.5
auto res = func(a);
cout << res << "\n";
}
int main() {
doSome([](int &a){
a += 2;
return 1;
});
doSome([](double &a){
a += 2.5;
return 1;
});
return 0;
}
Also while invoking templated functions, if I don't have to pass <any type hints> to the function, that would be much better solution.
There are a few issues with your approach. First, you can't partially specialize function templates, so that's out from the gate. Second, you're taking your function by lvalue reference - which prevents you from passing in a lambda, which is a prvalue.
In this case, it's easy to just add some SFINAE on your function template so that one only participates in overload resolution if it can be called with int& and the other only with double&:
template <class F>
auto doSome(F f)
-> decltype(f(std::declval<int&>()), void())
{
// int& case
}
template <class F>
auto doSome(F f)
-> decltype(f(std::declval<double&>()), void())
{
// double& case
}
If you want to make a generic version of doSome(), which doesn't use SFINAE for overload resolution, it gets a bit more complex.
#include <type_traits> // For std::remove_reference_t.
namespace detail {
// Helper to isolate return and parameter types, for a single-parameter callable.
template<typename T>
struct isolate_types;
// Function.
template<typename R, typename P>
struct isolate_types<R(P)> { using Ret = R; using Param = P; };
// Function pointer.
template<typename R, typename P>
struct isolate_types<R(*)(P)> { using Ret = R; using Param = P; }
// Pointer-to-member-function. Used for lambdas & functors.
// Assumes const this pointer.
template<typename R, typename C, typename P>
struct isolate_types<R (C::*)(P) const> { using Ret = R; using Param = P; };
// Lambda. Uses lambda's operator().
// Credit goes to ecatmur: http://stackoverflow.com/a/13359520/5386374
template<typename T>
struct isolate_types : isolate_types<decltype(&std::remove_reference_t<T>::operator())> {};
// Individual type aliases.
template<typename T>
using IsolateReturn = typename isolate_types<T>::Ret;
template<typename T>
using IsolateParam = typename isolate_types<T>::Param;
// Internal values, used by doSome().
template<typename T> T value;
template<> constexpr int value<int> = 5;
template<> constexpr double value<double> = 5.2;
// Define others as needed...
} // namespace detail
template<typename F>
void doSome(F func) {
// Determine necessary types.
using Ret = detail::IsolateReturn<F>;
using Param = std::remove_reference_t<detail::IsolateParam<F>>;
// And voila.
Param a = detail::value<Param>;
Ret res = func(a); // Can also use auto, if Ret isn't needed elsewhere.
std::cout << a << "\n";
}
Plugging this into your code... and it works.
Note that I'm not sure if this will work with all lambdas as written, and that it currently won't work with references to functions. It's easy enough to extend, however, by adding additional specialisations of isolate_types.

C++ function call wrapper with function as template argument

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

Implementing extended introspective swap algorithm

I know about ADL and the swap idiom:
using std::swap;
swap(x, y);
boost::swap() does the above for you. Now, I want to push it further. Specifically, Have the swap perform x.swap(y) if possible, and fallback to boost::swap() otherwise. So, you don't have to implement both a member swap and a free one, which is verbose and redundant. I tried to implement such a swap and ended up with the following. Implementing things like this can become quite tricky. So, I'm wondering whether there is any flaws in my implementation, or if more succinct implementations exist.
#include <algorithm>
#include <utility>
namespace cppu_detail_swap {
template <typename T>
void swap_impl(T& x, T& y) {
using std::swap;
swap(x, y);
}
} // namespace cppu_detail_swap
namespace cppu {
namespace detail {
template <typename T>
void swap(T& x, T& y, int) {
cppu_detail_swap::swap_impl(x, y);
}
template <typename T>
auto swap(T& x, T& y, char) -> decltype(x.swap(y)) {
return x.swap(y);
}
} // namespace detail
template <typename T>
void swap(T& x, T& y) {
detail::swap(x, y, ' ');
}
} // namespace cppu
Your current solution is flawed for objects from the cppu namespace, e.g.
// [insert your code here]
namespace cppu
{
struct X{};
struct Y{ void swap(Y& y) { }; };
}
int main()
{
auto x1 = cppu::X{};
auto x2 = cppu::X{};
swap(x1, x2);
auto y1 = cppu::Y{};
auto y2 = cppu::Y{};
swap(y1, y2);
}
g++ tells me:
taste.cpp:9:7: error: call of overloaded ‘swap(cppu::X&, cppu::X&)’ is ambiguous
To get rid of this, you need to explicitly call std::swap in swap_impl, which is OK, since you arrived here through the cppu::swap implementation already. But then you do not use overloads for other types. Thus, I think you need to distinguish three cases:
Has own swap member function
Has no swap member function and is from namespace cppu
Has no swap member function and is any other namespace (here you need to use the ADL swap idiom).
Also, I concur with #Yakk that I would be more direct instead of using the int/char hack.
So let's go for it:
A helper for checking the availability of the swap member:
namespace cppu
{
namespace detail
{
template <typename T>
using void_t = void;
template <typename T, typename = void>
struct has_member_swap
{
static constexpr bool value = false;
};
template <typename T>
struct has_member_swap<
T,
void_t<decltype(std::declval<T&>().swap(std::declval<T&>()))>>
{
static constexpr bool value = true;
};
}
}
And a helper to check if T is from namespace cppu, see also here:
namespace helper
{
template <typename T, typename = void>
struct is_member_of_cppu : std::false_type
{
};
template <typename T>
struct is_member_of_cppu<
T,
decltype(adl_is_member_of_cppu(std::declval<T>()))> : std::true_type
{
};
}
namespace cppu
{
template <typename T>
auto adl_is_member_of_cppu(T && ) -> void;
}
Now we can write all three overloads:
namespace cppu
{
namespace detail
{
template <
typename T,
typename = std::enable_if_t<helper::is_member_of_cppu<T>::value and
not has_member_swap<T>::value>>
auto swap(T& x, T& y)
-> std::enable_if_t<helper::is_member_of_cppu<T>::value and
not has_member_swap<T>::value>
{
std::cout << "cppu-type without member swap";
std::swap(x, y);
}
template <
typename T,
typename = std::enable_if_t<not helper::is_member_of_cppu<T>::value and
not has_member_swap<T>::value>>
auto swap(T& x, T& y)
-> std::enable_if_t<not helper::is_member_of_cppu<T>::value and
not has_member_swap<T>::value>
{
std::cout << "not cppu-type without member swap";
using std::swap;
swap(x, y);
}
template <typename T, typename = std::enable_if_t<has_member_swap<T>::value>>
auto swap(T& x, T& y) -> decltype(x.swap(y))
{
std::cout << "member swap";
return x.swap(y);
}
}
}
Call this as you did before:
namespace cppu
{
template <typename T>
void swap(T& x, T& y)
{
detail::swap(x, y);
}
}
And finally: Test the whole thing.
namespace cppu
{
struct X{};
struct Y{ void swap(Y& y) { }; };
}
struct A{};
struct B{ void swap(B& y) { }; };
struct C{};
auto swap(C&, C&) -> void { std::cout << " with own overload"; }
static_assert(helper::is_member_of_cppu<cppu::X>::value, "");
static_assert(helper::is_member_of_cppu<cppu::Y>::value, "");
static_assert(not helper::is_member_of_cppu<A>::value, "");
static_assert(not helper::is_member_of_cppu<B>::value, "");
int main()
{
auto x1 = cppu::X{};
auto x2 = cppu::X{};
std::cout << "X: "; swap(x1, x2); std::cout << std::endl;
auto y1 = cppu::Y{};
auto y2 = cppu::Y{};
std::cout << "Y: "; swap(y1, y2); std::cout << std::endl;
auto a1 = A{};
auto a2 = A{};
std::cout << "A: "; cppu::swap(a1, a2); std::cout << std::endl;
auto b1 = B{};
auto b2 = B{};
std::cout << "B: "; cppu::swap(b1, b2); std::cout << std::endl;
auto c1 = C{};
auto c2 = C{};
std::cout << "C: "; cppu::swap(c1, c2); std::cout << std::endl;
}
The output is as expected (IMHO):
X: cppu-type without member swap
Y: member swap
A: not cppu-type without member swap
B: member swap
C: not cppu-type without member swap with own overload

Function class accepting variable number of arguments from a container at runtime

I'm looking for a way to implement a function class
template<class ValueType>
class Function { ... };
which can be constructed with a function pointer (or functor) that takes any number of arguments of type ValueType and returns ValueType. For example, given these functions:
double foo(double);
double bar(double, double);
int baz(double, int);
a Function<double> object could be constructed with either foo or bar but not baz.
Then, a member function call will, given some container of ValueType (or an iterator), call the underlying function with the right number of arguments at runtime.
Is such thing possible?
It is indeed possible, you just have to "recursively" unpack arguments from the container and pass them to the function on the deepest level:
#include <cstddef>
#include <utility>
#include <stdexcept>
#include <functional>
#include <type_traits>
#include <vector>
#include <iostream>
namespace detail {
template <std::size_t argument_count>
struct arguments_unpacker {
template <typename Type, typename Function, typename InputIterator, typename... UnpackedArguments>
static Type unpack(Function&& function, InputIterator arguments_begin, InputIterator arguments_end, UnpackedArguments&&... unpacked_arguments) {
if (arguments_begin == arguments_end) {
throw std::invalid_argument("Not enough arguments.");
}
return arguments_unpacker<argument_count - 1>::template unpack<Type>(std::forward<Function>(function), std::next(arguments_begin), arguments_end, std::forward<UnpackedArguments>(unpacked_arguments)..., *arguments_begin);
}
};
template <>
struct arguments_unpacker<0> {
template <typename Type, typename Function, typename InputIterator, typename... UnpackedArguments>
static Type unpack(Function&& function, InputIterator arguments_begin, InputIterator arguments_end, UnpackedArguments&&... unpacked_arguments) {
if (arguments_begin != arguments_end) {
throw std::invalid_argument("Too many arguments.");
}
return function(std::forward<UnpackedArguments>(unpacked_arguments)...);
}
};
template <typename MemberFunction>
struct member_function_arity;
template <typename Result, typename Class, typename... Arguments>
struct member_function_arity<Result(Class::*)(Arguments...)> {
static constexpr std::size_t value = sizeof...(Arguments);
};
template <typename Result, typename Class, typename... Arguments>
struct member_function_arity<Result(Class::*)(Arguments...) const> {
static constexpr std::size_t value = sizeof...(Arguments);
};
template <typename Function>
struct function_arity : member_function_arity<decltype(&Function::operator())> {};
template <typename Result, typename... Arguments>
struct function_arity<Result(*)(Arguments...)> {
static constexpr std::size_t value = sizeof...(Arguments);
};
template <typename Result, typename... Arguments>
struct function_arity<std::function<Result(Arguments...)>> {
static constexpr std::size_t value = sizeof...(Arguments);
};
}
template <typename Type, typename InputIterator, typename Function>
std::function<Type(InputIterator, InputIterator)> variate(Function function) {
using namespace detail;
return [function](InputIterator arguments_begin, InputIterator arguments_end) {
return arguments_unpacker<function_arity<Function>::value>::template unpack<Type>(function, arguments_begin, arguments_end);
};
}
namespace demo {
double a(double x0) {
std::cout << "a(" << x0 << ")\n";
return 0.0;
}
double b(double x0, double x1) {
std::cout << "b(" << x0 << ", " << x1 << ")\n";
return 0.0;
}
double c(double x0, double x1, double x2) {
std::cout << "b(" << x0 << ", " << x1 << ", " << x2 << ")\n";
return 0.0;
}
auto l = [](double x0) mutable {
std::cout << "l(" << x0 << ")\n";
return 0.0;
};
void run() {
using it = std::vector<double>::const_iterator;
auto va = variate<double, it>(&a);
auto vb = variate<double, it>(&b);
auto vc = variate<double, it>(&c);
auto vl = variate<double, it>(l);
std::vector<double> a1 = {1.0};
std::vector<double> a2 = {1.0, 2.0};
std::vector<double> a3 = {1.0, 2.0, 3.0};
va(begin(a1), end(a1));
vb(begin(a2), end(a2));
vc(begin(a3), end(a3));
vl(begin(a1), end(a1));
}
}
int main()
{
demo::run();
return 0;
}
Note that this requres explicitly supplying iterator type. I don't see how it would be possible to remedy that without writing some kind of type erasing any_iterator.
#include <functional>
#include <boost/any.hpp>
template<class ValueType>
struct Function {
template <typename ...Args>
Function(const std::function<ValueType(Args...)>& f)
: fn(f)
{}
template <typename ...Args>
ValueType operator () (Args... args) {
auto f = boost::any_cast<const std::function<ValueType(Args...)>&>(fn);
return f(args...);
}
boost::any fn;
};
int a(int) { return 1; }
int b(int, double) { return 2; }
int main(int argc, char** argv)
{
typedef std::vector<Function<int>> Functions;
Functions functions {
std::function<int(int)>(a),
std::function<int(int, double)>(b)
};
std::cout << functions[0](1) << functions[1](1, 2.0) << std::endl;
}

c++0x: overloading on lambda arity

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