Functions and functors as arguments to template functions - c++

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)

There is no way to do what you want for a variety of reasons. But here is one that should make the problem pretty clear:
struct function_object
{
template<typename ...T>
void operator ()(T&&... v){}
};
f( function_object{} );
What is the type of the arguments of the function object passed to f? There isn't any, it can be called with any kind and number of arguments.

I also think there is no direct way to define the template parameters and function arguments of a single, primary template definition such that T can be deduced in all the different situations (function pointer, lambda expression, std::function argument etc.).
I would therefore recommend that you follow the approach suggested at the end of your question. Indeed neither std::function nor the tools offered by Boost (as far as I know) will easily enable this, though.
What I use (and I learnt that from other SO posts in the past), is a rather complicated template function_traits with specializations for all the different cases. My definition is this:
template <typename T>
struct function_traits
: public function_traits<decltype(&T::operator())>
{ };
template <typename Return, typename... Args>
struct function_traits<Return(Args...)>
{
typedef std::size_t size_type;
typedef Return result_type;
typedef result_type function_type(Args...);
static constexpr size_type arity = sizeof...(Args);
template <size_type index>
struct arg
{
typedef typename std::tuple_element<index,std::tuple<Args...>>::type type;
};
static constexpr bool value = true;
};
template <typename Return, typename... Args>
struct function_traits<Return(*)(Args...)>
: function_traits<Return(Args...)>
{ };
template <typename Return, typename... Args>
struct function_traits<Return(&)(Args...)>
: function_traits<Return(Args...)>
{ };
template <typename Class, typename Return, typename... Args>
struct function_traits<Return(Class::*)(Args...)>
: function_traits<Return(Args...)>
{ };
template <typename Class, typename Return, typename... Args>
struct function_traits<Return(Class::*)(Args...) volatile>
: function_traits<Return(Args...)>
{ };
template <typename Class, typename Return, typename... Args>
struct function_traits<Return(Class::*)(Args...) const>
: function_traits<Return(Args...)>
{ };
template <typename Class, typename Return, typename... Args>
struct function_traits<Return(Class::*)(Args...) const volatile>
: function_traits<Return(Args...)>
{ };
To make using this even more convenient, you may want to define using-aliases:
template <typename Fun>
using result_of = typename function_traits<Fun>::result_type;
template <typename Fun, std::size_t index>
using arg = typename function_traits<Fun>::template arg<index>::type;
With all these definitions (which in the below, I assume you put into a separate header more_type_traits.hpp), you can then easily define your wrapper function as follows:
#include <iostream>
#include <functional>
#include <type_traits>
#include "more_type_traits.hpp"
template <typename Fun>
using noref = typename std::remove_reference<Fun>::type;
template <typename Fun>
result_of<noref<Fun>> fun(Fun &&argfun)
{
// Default-initialize the first argument
arg<noref<Fun>,0> arg {};
// Call the function
return argfun(arg);
}
The below (which is basically copied from your code) then compiles and works for me:
void f1(int i)
{ std::cout << "f1(" << i << ')' << std::endl; }
struct f2_t
{
void operator()(int i)
{ std::cout << "f2(" << i << ')' << std::endl; }
};
int main()
{
fun(f1);
f2_t f2;
fun(f2);
std::function<void(int)> funobj = [](int i)
{ std::cout << "funobj(" << i << ')' << std::endl; };
fun(funobj);
fun( [](int i) { std::cout << "lambda(" << i << ')' << std::endl; } );
return 0;
}
Clearly, the definition of function_traits is complicated, because many different specializations are required. But it's worth the effort if you want to make function wrapping convenient.

Lets suppose I read in a comment that the OP really wants to take a function that mutates a T, and turn it into a function that mutates a std::vector<T>, and thinks that in order to do this you need to know what T is.
You don't
#include <type_traits>
#include <utility>
template<typename Lambda>
struct container_version {
Lambda closure;
container_version( container_version const& ) = default;
container_version( container_version && ) = default;
container_version( container_version & ) = default;
template<typename U>
container_version( U&& func ):closure(std::forward<U>(func)) {};
// lets make this work on any iterable range:
template<typename Container>
void operator()( Container&& c ) const {
for( auto&& x:c )
closure(x);
}
};
template<typename Lambda>
container_version< typename std::decay<Lambda>::type >
make_container_version( Lambda&& closure ) {
return {std::forward<Lambda>(closure)};
}
#include <vector>
#include <iostream>
#include <functional>
#include <array>
int main() {
std::vector<int> my_vec = {0, 1, 2, 3};
for (auto x:my_vec)
std::cout << x << ",";
std::cout << "\n";
make_container_version( []( int& x ) { x++; })( my_vec );
for (auto x:my_vec)
std::cout << x << ",";
std::cout << "\n";
// hey look, we can store it in a `std::function` if we need to:
auto super_func = make_container_version( []( int& x ) { x++; } );
std::function< void( std::vector<int>& ) > func = super_func;
// and the same super_func can be used for a function on a different container:
std::function< void( std::array<int,7>& ) > func2 = super_func;
func(my_vec);
for (auto x:my_vec)
std::cout << x << ",";
std::cout << "\n";
}
In fact, taking the argument and turning it into a std::function, or forcing it to be stored in a std::function, costs efficiency, increases the complexity of the code, and makes it unable to do things that it has no problem doing.
The above version, before it is packed into a std::function, can operate on sets, lists, vectors , raw C arrays, std::arrays, etc.

Related

Specializing function template based on lambda arity

I am trying to specialize a templated function based on the arity of the lambda that I pass to it as an argument. This is what I have come up with for a solution:
template<typename Function, bool>
struct helper;
template<typename Function>
struct helper<Function, false>
{
auto operator()(Function&& func)
{
std::cout << "Called 2 argument version.\n";
return func(1, 2);
}
};
template<typename Function>
struct helper<Function, true>
{
auto operator()(Function&& func)
{
std::cout << "Called 3 argument version.\n";
return func(1, 2, 3);
}
};
template<typename T>
struct B
{
T a;
const T someVal() const { return a; }
};
template<typename Function, typename T>
auto higherOrderFun(Function&& func, const T& a)
{
return helper<Function, std::is_invocable<Function, decltype(a.someVal()), decltype(a.someVal()), decltype(a.someVal())>::value>{}(std::forward<Function>(func));
}
int main()
{
B<int> b;
std::cout << higherOrderFun([](auto x, auto y) {return x+y; }, b) << "\n";
std::cout << higherOrderFun([](auto x, auto y, auto z) {return x + y+z; }, b) << "\n";
return 0;
}
Is there a way to achieve this in a more elegant manner? I've looked through this: Arity of a generic lambda
However, the latest solution (florestan's) turns all arguments into aribtrary_t, so one has to cast them back inside of each lambda, which I do not find ideal. Ideally I would have liked to directly specialize the templated higherOrderFun with SFINAE, but as it is I use a helper class in order to achieve that. Is there a more straighforward way? For instance to apply SFINAE directly to higherOrderFun without relying on a helper class? The whole point of this is to not have to change higherOrderFun into higherOrderFun2 and higherOrderFun3, but rather have the compiler deduce the correct specialization from the lambda and the given argument (const T& a).
I should mention that I also don't care about the type of the arguments to the function - just about their count, so I would have changed decltype(a.someVal()) to auto in my example if that was possible (maybe there's a way to circumvent explicitly defining the types?).
The following template gives me the number of parameters to a lambda, a std::function, or a plain function pointer. This seems to cover all the basics. So, you specialize on n_lambda_parameters<T>::n, and plug this into your template. Depending on your specific use cases, you may need to employ the facilities offered by std::remove_reference_t or std::decay_t, to wrap this.
Tested with g++ 9. Requires std::void_t from C++17, plenty of examples of simulating std::void_t pre C++17 can be found elsewhere...
#include <functional>
// Plain function pointer.
template<typename T> struct n_func_parameters;
template<typename T, typename ...Args>
struct n_func_parameters<T(Args...)> {
static constexpr size_t n=sizeof...(Args);
};
// Helper wrapper to tease out lambda operator()'s type.
// Tease out closure's operator()...
template<typename T, typename> struct n_extract_callable_parameters;
// ... Non-mutable closure
template<typename T, typename ret, typename ...Args>
struct n_extract_callable_parameters<T, ret (T::*)(Args...) const> {
static constexpr size_t n=sizeof...(Args);
};
// ... Mutable closure
template<typename T, typename ret, typename ...Args>
struct n_extract_callable_parameters<T, ret (T::*)(Args...)> {
static constexpr size_t n=sizeof...(Args);
};
// Handle closures, SFINAE fallback to plain function pointers.
template<typename T, typename=void> struct n_lambda_parameters
: n_func_parameters<T> {};
template<typename T>
struct n_lambda_parameters<T, std::void_t<decltype(&T::operator())>>
: n_extract_callable_parameters<T, decltype(&T::operator())> {};
#include <iostream>
void foo(int, char, double=0)
{
}
int main()
{
auto closure=
[](int x, int y)
// With or without mutable, here.
{
};
std::cout << n_lambda_parameters<decltype(closure)>::n
<< std::endl; // Prints 2.
std::cout << n_lambda_parameters<decltype(foo)>::n
<< std::endl; // Prints 3.
std::cout << n_lambda_parameters<std::function<void (int)>>::n
<< std::endl; // Prints 1.
return 0;
}
I would use different overloads:
template<typename Function>
auto higherOrderFun(Function&& func)
-> decltype(std::forward<Function>(func)(1, 2, 3))
{
return std::forward<Function>(func)(1, 2, 3);
}
template<typename Function>
auto higherOrderFun(Function&& func)
-> decltype(std::forward<Function>(func)(1, 2))
{
return std::forward<Function>(func)(1, 2);
}
Possibly with overload priority as
struct low_priority {};
struct high_priority : low_priority{};
template<typename Function>
auto higherOrderFunImpl(Function&& func, low_priority)
-> decltype(std::forward<Function>(func)(1, 2))
{
return std::forward<Function>(func)(1, 2);
}
template<typename Function>
auto higherOrderFunImpl(Function&& func, high_priority)
-> decltype(std::forward<Function>(func)(1, 2))
{
return std::forward<Function>(func)(1, 2);
}
template<typename Function>
auto higherOrderFun(Function&& func)
-> decltype(higherOrderFun(std::forward<Function>(func), high_priority{}))
{
return higherOrderFun(std::forward<Function>(func), high_priority{});
}
If you want to use the arity traits from florestan, it might result in:
template<typename F>
decltype(auto) higherOrderFun(F&& func)
{
if constexpr (arity_v<std::decay_t<F>, MaxArity> == 3)
{
return std::forward<F>(func)(1, 2, 3);
}
else if constexpr (arity_v<std::decay_t<F>, MaxArity> == 2)
{
return std::forward<F>(func)(1, 2);
}
// ...
}

Variadic templates - how can I create type, that stores passed arguments

So suppose, that I have got a class, that contains functional object and in the constructor call I pass arguments, that are to be passed to the functional object some time later. Something like:
class Binder{
public:
Binder(functional_object, listOfParameters);
callFunctionalObject(); // calls functional object with given list of parameters
};
Before C++11 I could not use Variadic templates, so one would do:
struct none{};
template <typename T1, typename T2=none, typename T3=none>
class Binder{
public:
Binder(T1 functionalObject, T2 arg1=none(), T3arg3=none());
void callFunctionalObject();
private:
T1 m_functionalObject;
T2 m_arg1;
T3 m_arg2;
};
Where callFunctionalobject could be implemented as follows:
template<typename T1, typename T2, typename T3>
void Binder<T1,T2,T3>::callFunctionalObject(){
callImpl(m_functionalObject, m_arg1, m_arg2);
}
and callImpl would be overloaded to recognize objects of type none to pass proper amount of arguments to the functional object.
Now switching to C++11 I do not know how to implement the fact, that in private section I have got members, to which I have an direct access.
Could anyone explain me the way I can do the same using C++11 or C++14?
You should store a std::function and a std::tuple and then call the function on the tuple.
Here a working C++14 solution
#include <iostream>
#include <functional>
template<typename T1, typename ...T>
class Binder
{
public:
Binder(std::function<T1(T...)> f, std::tuple<T...> t) : m_functional_obj(f), m_parameters(t) {}
template<std::size_t ...I>
T1 callImpl(std::index_sequence<I...>)
{
return m_functional_obj(std::get<I>(m_parameters)...);
}
T1 callFunctionalObject()
{
return callImpl(std::index_sequence_for<T...>{});
}
private:
std::function<T1(T...)> m_functional_obj;
std::tuple<T...> m_parameters;
};
int test(int i)
{
std::cout << "test(" << i << ")" << std::endl;
return i + 1;
}
int main()
{
Binder<int,int> bibi(test, std::make_tuple<int>(2));
auto res = bibi.callFunctionalObject();
std::cout << "res is " << res << std::endl;
}
Live code
My example:
// Indices
template <std::size_t... Is>
struct Indices {};
template <std::size_t N, std::size_t... Is>
struct BuildIndices : BuildIndices <N - 1, N - 1, Is...> {};
template <std::size_t... Is>
struct BuildIndices<0, Is...> : Indices < Is... > {};
template<class FuncObject, class ... T>
class Binder
{
public:
Binder(FuncObject funcObject, T... args)
: m_funcObject(funcObject), m_arguments(std::make_tuple(args...))
{
}
void Call()
{
DoCall(BuildIndices<sizeof ... (T)> {});
}
private:
template<size_t... Ind>
void DoCall(Indices<Ind...>)
{
return m_funcObject(std::get<Ind>(m_arguments)...);
}
FuncObject m_funcObject;
std::tuple<T...> m_arguments;
};
void Foo(int, char)
{
}
int main()
{
Binder<void(*)(int, char), int, char> f(Foo, 1, 'd');
f.Call();
return 0;
}
The simplest way is to store an std::function object with already-set arguments using std::bind:
class Binder{
public:
template <typename T1, typename... T2>
Binder(T1 functionalObject, T2... args) : f(std::bind(functionalObject, args...)) {}
void callFunctionalObject() { f(); }
private:
std::function<void()> f;
};
void foo(int n, std::string s) {
std::cout << n << " " << s << std::endl;
}
int main()
{
Binder b(foo, 42, "test");
b.callFunctionalObject();
}
If you need something more advanced, then you might want to store the function arguments in and std::tuple and then use some template magic to unwrap it, but please specify what exactly do you need in the question.
P.S. See also "unpacking" a tuple to call a matching function pointer

Can a template parameter itself be templatized?

Say I have the following code:
#include <iostream>
#include <functional>
template <int func(int)>
struct S : std::unary_function<int, int>
{
int operator()(int x) const
{
return func(x);
}
};
int foo(int x)
{
return x;
}
int main()
{
S<foo> s;
std::cout << s(42) << std::endl;
}
This works okay as a way of wrapping up a function inside of a functor, which means it can be used in other templated functions (like sort, for example (assuming the functor had the right signature)). I don't want to create a functor struct for every possible return/argument type (and realistically I can't), and so I tried the following:
template <template <typename R, // Make the return type and argument type template parameters!
typename A> R func(A)>
struct S : std::unary_function<R, A>
{
R operator()(A arg) const
{
return func(arg);
}
};
That didn't work; it gave me compilation errors. So then I tried:
template <typename R, typename A, R func(A)>
struct S : std::unary_function<R, A>
{
R operator()(A arg) const
{
return func(arg);
}
};
Which did work. Unfortunately though, I had to change instantiations of S to be S<int, int, foo> s; instead of the nicer S<foo> s;.
Is it at all possible to templatize the function passed as a template argument such that I can do S<foo> s; and not hard code the return type and argument type of the function in S?
My google-foo hasn't been able to find a specific answer.
Edit: Now I'm wondering if this isn't possible. I just thought of "what if foo is an overloaded function?" There wouldn't be, as far as I know, a way to know which foo to use when saying S<foo> s; and thus explicitly stating return/argument type is necessary. Is this correct thinking, and does this mean that the answer to my first question is "No, it's not possible"?
Unfortunately, I think it's the only way to prevent necessary conversions for passing functions.
But you can add function templates to help you deduce the types of (1) function args (2) function returns, like codes below:
template < typename R, typename A >
R result_of( R(A) );
template < typename R, typename A >
A arg0_of( R(A) );
Then you can use them to construct wanted function objects and let compilers do possible optimizations:
#define get_call( f ) call_t< decltype(result_of(f)), \
decltype(arg0_of(f)), f >()
// same as the class 'S'
template < typename R, typename A,
R unary( A ) >
struct call_t : std::unary_function<A,R> {
R operator()( A arg ) const {
return unary( arg );
}
};
Use the utility:
int neg( int arg ) {
return -arg;
}
auto s = get_call( neg );
cout << s( 1 ) << endl; // outputs: -1
It works too on function templates. Of course, you have to pass argument(s) to the template:
template < typename T >
T square( T arg ) {
return arg * arg;
}
template <>
int square( int arg ) {
cout << "square<int>()" << endl;
return arg * arg;
}
auto sq = get_call( square<int> );
cout << sq( 12 ) << endl; // outputs: square<int>()
// 144
Edit: for overloaded functions, you can do conversions to tell compilers which version you wanna invoke:
int cube( int arg ) {
return arg * arg * arg;
}
float cube( float arg ) {
return arg * arg * arg;
}
typedef float (*chosen)( float );
auto cu = get_call( (chosen)cube );
cout << showpoint << cu( 4 ) << endl; // outputs: 64.0000
You seem to want to have a non-type template template parameter. However, the only legal syntax for template template parameters is template < template-parameters > class. ("A template-argument for a template template-parameter shall be the name of a class template or an alias template, expressed as id-expression." § 14.3.3)
You could create a templated class whose constructor argument was a function pointer, but I'm guessing that you're worried that will create an indirect function call.
That is not possible. It is the same problem in principle as the following one: you wish to write just A<100> where A is defined as:
template<T N>
struct A {};
Given N is 100, T turns out to be int. Fine. That is deducible by human mind, but not by the compilers even if they be 100% conformant to the C++11 Standard. I've exactly the same problem here:
Pretty-print types and class template along with all its template arguments
--
So the alternative solution I think is this:
template <typename R, typename A>
struct S : std::unary_function<R, A>
{
typedef R (*Fun)(A);
Fun func;
S(Fun f) : func(f) {}
R operator()(A arg) const
{
return func(arg);
}
};
And then define MakeS function as:
template<typename R, typename A>
S<R,A> MakeS(R (*fun)(A))
{
return S<R,A>(fun);
}
Which you can use it as:
auto s = MakeS(foo);
Or, simply this:
S<int,int> s(foo);
The downside with this alternative is that the function foo doesn't have any chance to be inlined now.
Does this work for you?
It may not be as nice as S<foo> but keeps the arguments as 1 at the point of instantiation.
int f(int) { return 0; }
template<class R, class A> struct S
{
typedef R(*FTYPE)(A);
typedef R RET;
typedef A ARG;
};
template<class R, class A> S<R, A> FW(R(f)(A));
template<class T> struct F : std::unary_function<typename T::RET, typename T::ARG>
{
};
int main()
{
F<decltype(FW(f))> o;
}

Type sensitive tuple visitor

Suppose I have a std::tuple made up of types like
struct A {
static void tip();
};
struct B {
static void tip();
};
struct Z {
};
std::tuple<const A&,const B&,const Z&> tpl;
Yes, I need separate A, B. (The implementation of ::tip() differs for each type.) What I try to implement is a type-sensitive "visitor" that iterates through the tuple starting from the beginning to the end. Upon visiting a particular element of type T a function should be called depending on whether T has the ::tip() method or not. In the simple example of above only A and B have ::tip() implemented and Z not. So, the iterator should call twice the function for types with the ::tip() method and once the other function.
Here is what I came up with:
template< int N , bool end >
struct TupleIter
{
template< typename T , typename... Ts >
typename std::enable_if< std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
template< typename T , typename... Ts >
typename std::enable_if< ! std::is_function< typename T::tip >::value , void >::type
static Iter( const T& dummy , const std::tuple<Ts...>& tpl ) {
std::cout << "no tip\n";
std::get<N>(tpl); // do the work
TupleIter<N+1,sizeof...(Ts) == N+1>::Iter( std::get<N+1>(tpl) , tpl );
}
};
template< int N >
struct TupleIter<N,true>
{
template< typename T , typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};
I use a dummy instance of the type of the element at the iterator position and decide via enable_if which function to call. Unfortunately this doesn't work/isn't a nice solution:
The compiler complains about recursive instantiation
The const T& dummy is not a clean solution
I was wondering if enable_if is the right strategy to do the decision and how can one recursively iterate through the std::tuple capturing the first type and keeping all the remaining arguments in vital state. Read through How to split a tuple? but it doesn't do any decision.
How can one implement such a thing in a correct and portable way in C++11?
Well, it was harder than I expected, but this works.
Some things you were doing wrong/that I modified:
You can't evaluate this: std::is_function< typename T::tip >::value, since T::tip is not a type. Even if this could be evaluated, what would happen when T::tip does not exist? Substitution would still fail.
Since you use const references as your tuple's inner types, you had to clean them before trying to find the tip member inside them. By cleaning I mean removing const and removing the reference.
That dummy type stuff was not a good idea, there was no need to use that parameter. You can achieve the same thing using std::tuple_element, which retrieves the i-th type from a tuple.
I modified TupleIter's template parameters to the following, which means:
"TupleIter that processes the index-th type, inside a tuple of size n".
template<size_t index, size_t n>
struct TupleIter;
The whole code is this:
#include <tuple>
#include <iostream>
#include <type_traits>
struct A {
static void tip();
};
struct B {
static void tip();
};
struct Z {
};
// Indicates whether the template parameter contains a static member named tip.
template<class T>
struct has_tip {
template<class U>
static char test(decltype(&U::tip));
template<class U>
static float test(...);
static const bool value = sizeof(test<typename std::decay<T>::type>(0)) == sizeof(char);
};
// Indicates whether the n-th type contains a tip static member
template<size_t n, typename... Ts>
struct nth_type_has_tip {
static const bool value = has_tip<typename std::tuple_element<n, std::tuple<Ts...>>::type>::value;
};
// Generic iteration
template<size_t index, size_t n>
struct TupleIter
{
template< typename... Ts >
typename std::enable_if< nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl)
{
std::cout << "tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}
template< typename... Ts >
typename std::enable_if< !nth_type_has_tip<index, Ts...>::value , void >::type
static Iter(const std::tuple<Ts...>& tpl) {
std::cout << "no tip\n";
TupleIter<index + 1, n>::Iter(tpl );
}
};
// Base class, we've reached the tuple end
template<size_t n>
struct TupleIter<n, n>
{
template<typename... Ts >
static void Iter( const std::tuple<Ts...>& tpl ) {
std::cout << "end\n";
}
};
// Helper function that forwards the first call to TupleIter<>::Iter
template<typename... Ts>
void iterate(const std::tuple<Ts...> &tup) {
TupleIter<0, sizeof...(Ts)>::Iter(tup);
}
int main() {
A a;
B b;
Z z;
std::tuple<const A&,const B&,const Z&> tup(a,b,z);
iterate(tup);
}
Here is another take on the question, very similar to mfontanini answer, but showcasing:
boost::fusion::for_each (instead of manually iterate over the tuple).
A variant for implementing has_type using an expression-based SFINAE approach, that I feel a little bit simpler to follow than the usual sizeof trick.
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/fusion/algorithm.hpp>
#include <iostream>
struct nat // not a type
{
private:
nat();
nat(const nat&);
nat& operator=(const nat&);
~nat();
};
template <typename T>
struct has_tip
{
static auto has_tip_imp(...) -> nat;
template <typename U>
static auto has_tip_imp(U&&) -> decltype(U::tip());
typedef decltype(has_tip_imp(std::declval<T>())) type;
static const bool value = !std::is_same<type, nat>::value;
};
struct CallTip
{
template<typename T>
typename std::enable_if<has_tip<T>::value>::type
operator()(T& t) const
{
std::cout << "tip\n";
T::tip();
}
template<typename T>
typename std::enable_if<!has_tip<T>::value>::type
operator()(T& t) const
{
std::cout << "no tip\n";
return;
}
};
struct A {
static void tip(){}
};
struct B {
static void tip(){}
};
struct Z {
};
int main()
{
A a;
B b;
Z z;
boost::tuple<const A&,const B&,const Z&> tpl(a, b, z);
boost::fusion::for_each(tpl, CallTip());
}
Note that if your compiler support variadic template you can use std::tuple instead of boost::tuple inside fusion::for_each by including #include<boost/fusion/adapted/std_tuple.hpp>
Edit :
As pointed by Xeo in the comment, it is possible to simplify a lot the expression-SFINAE approach by removing completely the trait has_tip and simply forward to a little call helper.
The final code is really neat and tight !
#include <boost/tuple/tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/fusion/algorithm.hpp>
#include <iostream>
struct CallTip
{
template<typename T>
void operator()(const T& t) const
{
call(t);
}
template<class T>
static auto call(const T&) -> decltype(T::tip())
{
std::cout << "tip\n";
T::tip();
}
static void call(...)
{
std::cout << "no tip\n";
}
};
struct A {
static void tip(){}
};
struct B {
static void tip(){}
};
struct Z {
};
int main()
{
A a;
B b;
Z z;
boost::tuple<const A&,const B&,const Z&> tpl(a, b, z);
boost::fusion::for_each(tpl, CallTip());
}

SFINAE: detect if class has free function

Is there a way, using SFINAE, to detect whether a free function is overloaded for a given class?
Basically, I’ve got the following solution:
struct has_no_f { };
struct has_f { };
void f(has_f const& x) { }
template <typename T>
enable_if<has_function<T, f>::value, int>::type call(T const&) {
std::cout << "has f" << std::endl;
}
template <typename T>
disable_if<has_function<T, f>::value, int>::type call(T const&) {
std::cout << "has no f" << std::endl;
}
int main() {
call(has_no_f()); // "has no f"
call(has_f()); // "has f"
}
Simply overloading call doesn’t work since there are actually a lot of foo and bar types and the call function has no knowledge of them (basically call is inside a and the users supply their own types).
I cannot use C++0x, and I need a working solution for all modern compilers.
Note: the solution to a similar question unfortunately doesn’t work here.
#include <iostream>
#include <vector>
#include <algorithm>
#include <utility>
#include <functional>
#include <type_traits>
struct X {};
struct Y {};
__int8 f(X x) { return 0; }
__int16 f(...) { return 0; }
template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) {
std::cout << "In call with f available";
f(t);
return 0;
}
template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) {
std::cout << "In call without f available";
return 0;
}
int main() {
Y y; X x;
call(y);
call(x);
}
A quick modification of the return types of f() yields the traditional SFINAE solution.
If boost is allowed, the following code might meet your purpose:
#include <boost/type_traits.hpp>
#include <boost/utility/enable_if.hpp>
using namespace boost;
// user code
struct A {};
static void f( A const& ) {}
struct B {};
// code for has_f
static void f(...); // this function has to be a free standing one
template< class T >
struct has_f {
template< class U >
static char deduce( U(&)( T const& ) );
template< class U, class V >
static typename disable_if_c< is_same< V, T >::value, char(&)[2] >::type
deduce( U(&)( V const& ) );
static char (&deduce( ... ))[2];
static bool const value = (1 == sizeof deduce( f ));
};
int main()
{
cout<< has_f<A>::value <<endl;
cout<< has_f<B>::value <<endl;
}
However, there are severe restrictions.
The code assumes that all the user functions have the signature ( T const& ),
so ( T ) isn't allowed.
The function void f(...) in the above seems to need to be a free standing
function.
If the compiler enforces two phase look-up as expected normally, probably
all the user functions have to appear before the definition of has_f class
template.
Honestly, I'm not confident of the usefulness of the code, but anyway I hope
this helps.