特化一个class时,如何取不同数量的模板参数?
When specializing a class, how can I take a different number of template parameters?
我刚问了这个问题: and 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>&);
是否没有要求特化必须采用相同数量的参数?
Are there no requirements that specializations must take the same number of parameters?
有;并对您的示例感到满意。
写的时候
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...)
。
从单一类型 R(T::*)(Args...)
,您可以推断出多个模板参数(R
、T
和可变参数 Args...
,在此示例中)但是类型 R(T::*)(Args...)
(接收可变参数列表的 class 的方法)保持为一个。
For example, is something like this legal?
template<typename T>
void foo(const T&);
template<typename K, typename V>
void foo<pair<K, V>>(const pair<K, V>&);
不,但是(如评论中所写)第二个不是 class/struct 部分特化(其中 std::pair<K, V>
保持单一类型),这是合法的;这是一个被禁止的模板 function 偏特化。
但是你可以完全专门化一个模板函数;所以这是合法的(例如)
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;
};
您似乎混淆了显式特化的模板参数和用于特化模板的模板实参。
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
这里也是一样。是的,显式特化不带任何参数,但这仅意味着要推导 none,实际上您正在显式编写模板参数 (void
),因此特化的模板参数数量与主模板匹配。
您的示例无效,因为您不能部分特化函数。
我刚问了这个问题:
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>&);
是否没有要求特化必须采用相同数量的参数?
Are there no requirements that specializations must take the same number of parameters?
有;并对您的示例感到满意。
写的时候
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...)
。
从单一类型 R(T::*)(Args...)
,您可以推断出多个模板参数(R
、T
和可变参数 Args...
,在此示例中)但是类型 R(T::*)(Args...)
(接收可变参数列表的 class 的方法)保持为一个。
For example, is something like this legal?
template<typename T>
void foo(const T&);
template<typename K, typename V>
void foo<pair<K, V>>(const pair<K, V>&);
不,但是(如评论中所写)第二个不是 class/struct 部分特化(其中 std::pair<K, V>
保持单一类型),这是合法的;这是一个被禁止的模板 function 偏特化。
但是你可以完全专门化一个模板函数;所以这是合法的(例如)
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;
};
您似乎混淆了显式特化的模板参数和用于特化模板的模板实参。
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
这里也是一样。是的,显式特化不带任何参数,但这仅意味着要推导 none,实际上您正在显式编写模板参数 (void
),因此特化的模板参数数量与主模板匹配。
您的示例无效,因为您不能部分特化函数。