I'm looking for a way to pass function pointers, functors or lambdas to a template function g which uses the passed function's argument types, for example:
template<class T1, class T2, class T3>
struct wrapper_t {
boost::function<void(T1,T2,T3)> f;
wrapper_t( boost::function<void(T1,T2,T3)> f ) : f(f) {}
void operator( std::vector<T1> &a, std::vector<T2> &b, T3 c ) {
assert(a.size() == b.size());
for(size_t i = 0 ; i != a.size() ; i++) f(a[i], b[i], c);
}
};
template<class T1, class T2, class T3>
wrapper_t<T1,T2,T3> make_wrapper( boost::function<void(T1,T2,T3)> f ) {
return wrapper_t<T1,T2,T3>( f );
}
void f(int, double, char) {};
wrapper_t<int, double, char> w0(f); // need to repeat types
auto w1 = make_wrapper(f); // more comfortable
std::vector<int> a{{1, 2, 3}};
std::vector<double> b{{1.0, 2.0, 3.0}};
w0( a, b, 'c' );
w1( a, b, 'c' );
The make_wrapper function only exists to extract the types from the argument, some syntactic sugar to avoid having to type them twice.
A minimal example for my problem is this function:
template<class T>
void g1( const boost::function<void(T)> & ) {}
Using these as input
void f1(int) {}
struct f2_t { void operator()(int) {} };
it fails to infer T=int
f2_t f2;
g1( f1 ); // mismatched types ‘const std::function<void(T)>’ and ‘void(int)’
g1( f2 ); // ‘f2_t’ is not derived from ‘const std::function<void(T)>’
g1( [](int){} ); // ‘::<lambda(int)>’ is not derived from ‘…
g1<int>( f1 ); // ok
g1<int>( f2 ); // ok
g1<int>( [](int){} ); // ok
But T=int can be inferred from a plain function pointer, but of this doesn't work with the functor or lambda either:
template<class T>
void g2( void (*)(T) ) {}
g2( f1 ); // ok
g2( f2 ); // mismatched types …
g2<int>( f2 ); // ok
g2( [](int){} ); // mismatched types …
g2<int>( [](int){} ); // ok
Is there a way to infer T not just for plain function pointers but for functors and lambdas, too?
Or does it have to be something like this?
template<class F>
void g( F ) { typedef first_argument_of<F>::type T; }
(in my real code I need to deconstruct a function with four arguments this way, but std::function::…argument_type only exists for one or two arguments; boost::function has argN_type, but I don't think I can use that anyway since F is not always a function which is my problem, see above, etc)
Tfrom to feed thistemplatededucedstd::function<void(T)>in order to invoke it? - Yakk - Adam Nevraumont