我刚刚问了一个问题:Can I get the Owning Object of a Member Function Template Parameter?和Yakk - 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>&);
是否没有要求专业化必须使用相同数量的参数?
答案 0 :(得分:5)
您似乎混淆了显式专门化的模板参数和用于专门化模板的模板参数。
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
),因此专业化的模板参数数量与主要模板。
您的示例无效,因为您无法部分专门化功能。
答案 1 :(得分:4)
是否没有要求专业化必须使用相同数量的参数?
有;并在您的示例中感到满意。
写作时
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...)
,您可以推断出一个模板参数(在此示例中为R
,T
和可变参数Args...
),但类型为{ {1}}(一种接收各种参数列表的类方法)保持不变。
例如,这样合法吗?
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