在专攻类时,如何采用不同数量的模板参数?

When specializing a class, how can I take a different number of template parameters?

本文关键字:参数 何采用      更新时间:2023-10-16

我刚刚问了这个问题: 我能否获取成员函数模板参数的拥有对象? 和雅克 - Adam Nevraumont的回答有代码:

template<class T>
struct get_memfun_class;
template<class R, class T, class...Args>
struct get_memfun_class<R(T::*)(Args...)> {
using type=T;
};

这些显然是最初的声明,然后是struct get_memfun_class的专业化。但我发现自己不确定:专业化可以有不同的模板参数数量吗?

例如,这样的事情合法吗?

template<typename T>
void foo(const T&);
template<typename K, typename V>
void foo<pair<K, V>>(const pair<K, V>&);

是否没有要求专业化必须采用相同数量的参数?

您似乎混淆了显式专用化的模板参数和用于专用化模板的模板参数。

template<class T> // one argument
struct get_memfun_class; // get_memfun_class takes one template (type) argument
template<class R, class T, class...Args>
struct get_memfun_class<R(T::*)(Args...)> {
//                      ^^^^^^^^^^^^^^^^
//                      one type argument
using type=T;
}; // explicit specialization takes one template argument

是的,显式专用化有三个模板参数,但这并不意味着显式专用化需要三个参数。他们在那里被推断出来。您可以使用多个类型参数形成单个类型,这就是那里正在发生的事情。还要考虑您可以完全专用化模板:

template <>
struct get_memfun_class<void>;
//                      ^^^^
//                    one type argument

这是一回事。是的,显式专用化不需要任何参数,但这只意味着没有可推导的参数,并且您确实在显式编写模板参数(void(,因此专用化的模板参数数量与主模板的参数数量匹配。

您的示例无效,因为您无法部分专用化函数。

是否没有要求专业化必须采用相同数量的参数?

有;并且对你的例子感到满意。

当你写的时候

template<class T>
struct get_memfun_class;

你说get_mumfun_class是一个模板struct,只有一个模板typename参数;当你写的时候

template<class R, class T, class...Args>
struct get_memfun_class<R(T::*)(Args...)> {
using type=T;
};

定义一个专用化,该专用化以R(T::*)(Args...)的形式接收单个模板 TypeName 参数。

从单个类型R(T::*)(Args...),你可以推导出多个模板参数(RT和这个例子中的可变参数Args...(,但类型R(T::*)(Args...)(接收参数的可变参数列表的类的方法(仍然是一个。

例如,这样的事情合法吗?

template<typename T>
void foo(const T&);
template<typename K, typename V>
void foo<pair<K, V>>(const pair<K, V>&);

不,但是(如注释中所写(第二个不是类/结构部分专用化(std::pair<K, V>仍然是单一类型(,这是合法的;它是禁止的模板函数部分专用化。

但是你可以完全专化一个模板函数;所以它是合法的(通过示例(

template<>
void foo<std::pair<long, std::string>(const std::pair<long, std::string>&);

法律上是get_memfun_class的完全专业化(再举一个例子(

template<>
struct get_memfun_class<std::pair<long, std::string>> {
using type=long long;
};