如何专门化模板函数以区分无效和非无效函数参数
How to specialize template function to distinguish void and non-void function arguments
我想要 2 个功能:接受 void(*)(int)
和 int(*)(int)
。
如何写 type_trait 类似于 std::is_invocable_r 但检查确切的 return 类型(因为任何函数都可以转换为函数 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...>
导致歧义,因为任何类型都可以转换为 void。
std::is_same_v<R, std::invoke_result_t<C, Args...>>
导致替换失败。
问题是当 C
不能用 Args...
调用时,你的特征格式不正确,你必须 SFINAE 你的变量:
template <typename R, typename C, typename TupleArgs, typename Enabler = void>
constexpr bool is_exact_invocable_r_v_impl = false;
template <typename R, typename C, typename... Args>
constexpr bool is_exact_invocable_r_v_impl<R,
C,
std::tuple<Args...>,
std::void_t<std::invoke_result_t<C, Args...>>> =
std::is_same_v<R, std::invoke_result_t<C, Args...>>;
template <typename R, typename C, typename... Args>
constexpr bool is_exact_invocable_r_v =
is_exact_invocable_r_v_impl<R, C, std::tuple<Args...>>;
我想要 2 个功能:接受 void(*)(int)
和 int(*)(int)
。
如何写 type_trait 类似于 std::is_invocable_r 但检查确切的 return 类型(因为任何函数都可以转换为函数 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...>
导致歧义,因为任何类型都可以转换为 void。
std::is_same_v<R, std::invoke_result_t<C, Args...>>
导致替换失败。
问题是当 C
不能用 Args...
调用时,你的特征格式不正确,你必须 SFINAE 你的变量:
template <typename R, typename C, typename TupleArgs, typename Enabler = void>
constexpr bool is_exact_invocable_r_v_impl = false;
template <typename R, typename C, typename... Args>
constexpr bool is_exact_invocable_r_v_impl<R,
C,
std::tuple<Args...>,
std::void_t<std::invoke_result_t<C, Args...>>> =
std::is_same_v<R, std::invoke_result_t<C, Args...>>;
template <typename R, typename C, typename... Args>
constexpr bool is_exact_invocable_r_v =
is_exact_invocable_r_v_impl<R, C, std::tuple<Args...>>;