Question

I want to write function overload switched by arguments functor(function pointer, function object or lambda)'s arguments. So, functor arguments is (int) or (int, int).

My bad implementation is hare.

void function_int(int){
    return;
};

void function_int_int(int, int){
    return;
}

template <typename Functor>
boolean some_func(Functor functor) { 
    // bad implementation.
    return true;
}

int main(const int an, const char* const* const as)
{
    auto lambda_int = [&](int i) -> void {
    };
    auto lambda_int_int = [&](int i, int j) -> void {
    };

    struct functor_int {
        void operator ()(int i) {
        }
    };

    struct functor_int_int {
        void operator ()(int i, int j) {
        }
    };

    some_func(function_int);     // want true
    some_func(function_int_int); // false
    some_func(functor_int());    // true
    some_func(functor_int_int());// false
    some_func(lambda_int);       // true
    some_func(lambda_int_int);   // false
}

Is it possible in C++? Please give me some idea.

Was it helpful?

Solution

The problem is only solvable if the functors do not have multiply overloaded operator(), nor default arguments. Fortunately both are always true of lambdas.

You can discover what arguments a lambda type T takes by inspecting & T::operator().

template< typename sig >
struct ptmf_args_to_tuple;

template< typename c, typename r, typename ... a >
struct ptmf_args_to_tuple< r (c::*)( a ... ) > {
    typedef std::tuple< a ... > type;
};

template< typename c, typename r, typename ... a >
struct ptmf_args_to_tuple< r (c::*)( a ... ) const > {
    typedef std::tuple< a ... > type;
};

template< typename fn >
struct functor_args_to_tuple {
    typedef typename ptmf_args_to_tuple< decltype( & fn::operator () ) >::type type;
};

Use the metafunction to let the overloads discriminate by SFINAE:

template <typename Functor>
typename std::enable_if<
    std::tuple_size< typename functor_args_to_tuple< Functor >::type >
                   ::value == 1,
    boolean >::type
some_func(Functor functor) { 
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top