jeudi 2 avril 2020

How to specialize template function to distinguish void and non-void function arguments

I'd like to have 2 functions: accepting void(*)(int) and int(*)(int). How to write type_trait similar to std::is_invocable_r but checking exact return type (because any function can be cast to function returning void).

#include <functional>
#include <type_traits>
#include <cstdio>

template <typename R, typename C, typename... Args>
constexpr bool is_exact_invocable_r_v =
        std::is_same_v<R, std::invoke_result_t<C, Args...>>;
        // std::is_invocable_r_v<R, C, Args...>;

template<typename C, std::enable_if_t<is_exact_invocable_r_v<int, C>, int> = 0>
void print(C)
{
    printf("1\n");
}

template<typename C, std::enable_if_t<is_exact_invocable_r_v<int, C, int>, int> = 0>
void print(C)
{
    printf("2\n");
}

template<typename C, std::enable_if_t<is_exact_invocable_r_v<void, C, int>, int> = 0>
void print(C)
{
    printf("3\n");
}

int main()
{
    print([](){return 0;});
    print([](int){return 0;});
    print([](int){});
}

std::is_invocable_r_v<R, C, Args...> causes ambiguity because any type can be cast to void.

std::is_same_v<R, std::invoke_result_t<C, Args...>> causes substitution failure.

Aucun commentaire:

Enregistrer un commentaire