当部分特化的参数不使用其任何模板参数时适用哪些规则

Which rules apply when an argument of partial specialization does not use any of its template parameters

n4567 [temp.class.spec.match]p2

A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list (14.8.2).

template<class T, class U>
struct S{};

template<class U>
struct S<int, U>{};

S<char, int> s;

我知道偏特化 S<int, U> 与实际的模板参数列表 char, int 不匹配,第二个参数 U 可以从 int 推导出来 14.8。 2.5.

但是我不知道14.8.2中的哪些规则适用于第一个参数int

14.8.2.5 [temp.deduct.type]p1

Template arguments can be deduced in several different contexts, but in each case a type that is specified in terms of template parameters (call it P) is compared with an actual type (call it A), and an attempt is made to find template argument values (a type for a type parameter, a value for a non-type parameter, or a template for a template parameter) that will make P, after substitution of the deduced values (call it the deduced A), compatible with A.

根据我的理解,S<int, U> 中的 int 不是 根据模板参数指定的,因此 14.8.2.5 不是申请。

我想知道处理这种情况的规则是什么,或者你可以纠正我 14.8.2.5


换句话说: 直觉上,偏特化 S<int, U> 不匹配 char,int 因为 char 不匹配 int

我想知道哪些规则决定char不匹配int

In my understanding the int in S is not specified in terms of template parameters, so 14.8.2.5 does not apply.

不,14.8.2.5 解释了如何 推断类型,14.3 处理模板参数并且您发布的代码失败 14.3p1 :

14.3p1 ... The type and form of each template-argument specified in a template-id shall match the type and form specified for the corresponding parameter declared by the template in its template parameter-list.

template<class T, class U>
struct S<int, U> {}; 
// compiler error, template parameters not used in partial specialization

应该是

template<class U>
struct S<int, U> {};

所以,

#1
template<class T, class U>
struct S{};

#2
template<class U>
struct S<int, U> {};

S<char, int> s; // uses #1
S<int, char> c; // uses #2 since S<int, U> matches more closely than S<T, U>

您提到 gcc 拒绝了模板,而 clang 接受了模板。在我的测试中,VC++gcc 默认情况下给出编译器错误并且根本没有编译代码,但是 clang 给出警告而不是说明 this partial specialization will never be used 和无论如何构建二进制文件。因此,在所有情况下,它都会发出 non-conformity 的通知,这只是默认情况下启用的编译器设置以及编译器实现如何处理 non-conforming 代码的问题。

希望能帮到你。

当考虑这里发生的事情时:

template<class T, class U> struct S{}; // (1)
template<class U> struct S<int, U>{};  // (2)

S<char, int> s; // (1) or (2)?

为了确定我们为 s 使用的专业化,我们进入 [temp.class.spec.match]:

When a class template is used in a context that requires an instantiation of the class, it is necessary to determine whether the instantiation is to be generated using the primary template or one of the partial specializations. This is done by matching the template arguments of the class template specialization with the template argument lists of the partial specializations.

在本例中,我们将 <char, int><int, U> 进行匹配。匹配是什么意思?

A partial specialization matches a given actual template argument list if the template arguments of the partial specialization can be deduced from the actual template argument list (14.8.2).

基本上,我们推导出 U 来匹配 int == charU == int。等价地,我们正在考虑推导 U in:

template <class U> void f(S<int, U> );
f(S<char, int>{} );

没有这样的推论。

这导致我们:

— If no matches are found, the instantiation is generated from the primary template.

这导致我们 (1)

我们来看一个更有趣的案例:

S<int, char> s2;

现在,<int, char> 匹配 <int, U>,因为我们可以推导出 U=char。因此:

— If exactly one matching specialization is found, the instantiation is generated from that specialization.

这导致我们 (2)