I\'m not sure if it\'s possible, so that\'s what I want to find out.
I\'d like to create a function which accepts any kind of functor/callable object, but I want to
Here's an example that will work for most callables including functors and lambdas (although not for generic functors as @Yakk demonstrated in a comment on the question).
The code can also be useful when determining return type and multiple arguments.
template <typename T>
struct func_traits : public func_traits<decltype(&T::operator())> {};
template <typename C, typename Ret, typename... Args>
struct func_traits<Ret(C::*)(Args...) const> {
using result_type = Ret;
template <std::size_t i>
struct arg {
using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
};
template <typename T>
void option(T&& t) {
using traits = func_traits<typename std::decay<T>::type>;
using return_t = typename traits::result_type; // Return type.
using arg0_t = typename traits::template arg<0>::type; // First arg type.
// Output types.
std::cout << "Return type: " << typeid(return_t).name() << std::endl;
std::cout << "Argument type: " << typeid(arg0_t).name() << std::endl;
}
To add support for regular functions add a specialization e.g.
template <typename Ret, typename... Args>
struct func_traits<Ret(*)(Args...)> { /* ... */ }
More useful info: Is it possible to figure out the parameter type and return type of a lambda?
template < typename T >
void option( function< void(T) > )
{
cout << typeid( T ).name() << endl;
}
template < typename T >
void option( void (*func)(T) )
{
option( function< void(T) >( func ) );
}
template< typename F, typename A >
void wrapper( F &f, void ( F::*func )( A ) const )
{
option( function< void(A) >( bind( func, f, placeholders::_1 ) ) );
}
template< typename F, typename A >
void wrapper( F &f, void ( F::*func )( A ) )
{
option( function< void(A) >( bind( func, f, placeholders::_1 ) ) );
}
template < typename T >
void option( T t )
{
wrapper( t, &T::operator() );
}
void test( int )
{
}
struct Object
{
void operator ()( float )
{
}
};
int main( int, char *[] )
{
Object obj;
option( test );
option( [](double){} );
option( obj );
return 0;
}
Based on information found here c++0x: overloading on lambda arity, which I found through @dyps link
This isn't the best solution, since it requires overloads for const/non-const/volatile etc. It does get the job done in terms of the original problem I was trying to solve...