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.

Était-ce utile?

La 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) { 
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top