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

不羁岁月 提交于 2019-12-23 04:09:22

问题


I just asked this question: Can I get the Owning Object of a Member Function Template Parameter? and Yakk - Adam Nevraumont's answer had the code:

template<class T>
struct get_memfun_class;

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

These is clearly an initial declaration and then a specialization of struct get_memfun_class. But I find myself uncertain: Can specializations have a different number of template parameters?

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>&);

Are there no requirements that specializations must take the same number of parameters?


回答1:


You seem to confuse the template parameters of the explicit specialization and the template arguments you use to specialize the template.

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

Yes, there are three template parameters for the explicit specialization, but that doesn't mean that the explicit specialization takes three arguments. They are there to be deduced. You can form a single type using multiple type parameters, which is what is happening there. Also consider that you can fully specialize a template:

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

Here it's the same thing. Yes, the explicit specialization takes no parameters, but that just means that there is none to be deduced and indeed you are explicitly writing a template parameter (void) and so the amount of template arguments of the specialization match those of the primary template.

Your example is invalid because you cannot partially specialize functions.




回答2:


Are there no requirements that specializations must take the same number of parameters?

There is; and is satisfied in your example.

When you write

template<class T>
struct get_memfun_class;

you say that get_mumfun_class is a template struct with a single template typename argument; and when you write

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

you define a specialization that receive a single template typename argument in the form R(T::*)(Args...).

From the single type R(T::*)(Args...), you can deduce more that one template paramenters (R, T and the variadic Args..., in this example) but the type R(T::*)(Args...) (a method of a class that receive a variadic list of arguments) remain one.

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>&);

No, but (as written in comments) the second one isn't a class/struct partial specialization (where std::pair<K, V> remain a single type), that is legal; it's a template function partial specialization that is forbidden.

But you can full specialize a template function; so it's legal (by example)

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

as is legal the full specialization for get_memfun_class (to make another example)

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


来源:https://stackoverflow.com/questions/52318110/when-specializing-a-class-how-can-i-take-a-different-number-of-template-paramet

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!