La spécialisation partielle non-classe et non variable n'est pas autorisée, mais comme indiqué:
Tous les problèmes en informatique peuvent être résolus par un autre niveau d'indirection. —— David Wheeler
L'ajout d'une classe pour transférer l'appel de fonction peut résoudre ce problème, voici un exemple:
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, "");