Non-classical, non-variable partial specialization is not allowed, but, as said:
All problems in computer science can be solved by a different level of indirection. - David Wheeler
Adding a class to forward a function call may solve this, here is an example:
template <class Tag, class R, class... Ts> struct enable_fun_partial_spec; struct fun_tag {}; template <class R, class... Ts> constexpr R fun(Ts&&... ts) { return enable_fun_partial_spec<fun_tag, R, Ts...>::call( std::forward<Ts>(ts)...); } template <class R, class... Ts> struct enable_fun_partial_spec<fun_tag, R, Ts...> { constexpr static R call(Ts&&... ts) { return {0}; } }; template <class R, class T> struct enable_fun_partial_spec<fun_tag, R, T, T> { constexpr static R call(T, T) { return {1}; } }; template <class R> struct enable_fun_partial_spec<fun_tag, R, int, int> { constexpr static R call(int, int) { return {2}; } }; template <class R> struct enable_fun_partial_spec<fun_tag, R, int, char> { constexpr static R call(int, char) { return {3}; } }; template <class R, class T2> struct enable_fun_partial_spec<fun_tag, R, char, T2> { constexpr static R call(char, T2) { return {4}; } }; static_assert(std::is_same_v<decltype(fun<int>(1, 1)), int>, ""); static_assert(fun<int>(1, 1) == 2, ""); static_assert(std::is_same_v<decltype(fun<char>(1, 1)), char>, ""); static_assert(fun<char>(1, 1) == 2, ""); static_assert(std::is_same_v<decltype(fun<long>(1L, 1L)), long>, ""); static_assert(fun<long>(1L, 1L) == 1, ""); static_assert(std::is_same_v<decltype(fun<double>(1L, 1L)), double>, ""); static_assert(fun<double>(1L, 1L) == 1, ""); static_assert(std::is_same_v<decltype(fun<int>(1u, 1)), int>, ""); static_assert(fun<int>(1u, 1) == 0, ""); static_assert(std::is_same_v<decltype(fun<char>(1, 'c')), char>, ""); static_assert(fun<char>(1, 'c') == 3, ""); static_assert(std::is_same_v<decltype(fun<unsigned>('c', 1)), unsigned>, ""); static_assert(fun<unsigned>('c', 1) == 4, ""); static_assert(std::is_same_v<decltype(fun<unsigned>(10.0, 1)), unsigned>, ""); static_assert(fun<unsigned>(10.0, 1) == 0, ""); static_assert( std::is_same_v<decltype(fun<double>(1, 2, 3, 'a', "bbb")), double>, ""); static_assert(fun<double>(1, 2, 3, 'a', "bbb") == 0, ""); static_assert(std::is_same_v<decltype(fun<unsigned>()), unsigned>, ""); static_assert(fun<unsigned>() == 0, "");