在对类进行专业化处理时,如何使用不同数量的模板参数?

时间:2018-09-13 16:33:43

标签: c++ templates language-lawyer variadic-templates template-specialization

我刚刚问了一个问题: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>&);

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

2 个答案:

答案 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...),您可以推断出一个模板参数(在此示例中为RT和可变参数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