C ++ 11别名模板作为专门化中的模板模板参数?

时间:2023-01-15 17:47:28

Why doesn't the follow C++11 program compile?

为什么不遵循C ++ 11程序编译?

template<template<typename> class X, typename Y> struct C;
template<template<typename> class X, typename Z> struct C<X, X<Z>> {};

template<typename T> using A = T*;

int main()
{
    C<A, A<int>> c;
}

The error is:

错误是:

aggregate ‘C<A, int*> c’ has incomplete type and cannot be defined

Why doesn't the partial specialization of C match C<A, A<int>>?

为什么C的部分特化不匹配C >? ,a>

3 个解决方案

#1


4  

I think that 14.5.7 Alias templates:

我认为14.5.7 Alias模板:

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template.

当template-id引用别名模板的特化时,它等同于通过替换别名模板的type-id中的template-parameters的template-arguments获得的关联类型。

would apply, so X<Z> would be interpreted as Z* as soon as X is known to be an alias template. The syntax for a partial specialisation does indeed use the template-id grammar rule. However, template argument substitution takes place as the last step in template argument deduction, only once all template arguments have been deduced.

将适用,因此只要知道X是别名模板,X 就会被解释为Z *。部分特化的语法确实使用了模板ID语法规则。但是,模板参数替换是模板参数推导的最后一步,只有在推导出所有模板参数后才会发生。

14.5.5.1 Matching of class template partial specializations [temp.class.spec.match]

14.5.5.1类模板部分特化的匹配[temp.class.spec.match]

2 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).

2如果可以从实际模板参数列表中推导出部分特化的模板参数,则部分特化匹配给定的实际模板参数列表(14.8.2)。

14.8.2 Template argument deduction [temp.deduct]

14.8.2模板参数推导[temp.deduct]

5 When all template arguments have been deduced or obtained from default template arguments, all uses of template parameters in the template parameter list of the template and the function type are replaced with the corresponding deduced or default argument values.

5当从默认模板参数推断或获得所有模板参数时,模板的模板参数列表中的模板参数的所有使用和函数类型将替换为相应的推导或默认参数值。

Without template argument substitution of X, Z cannot be deduced. So, the specialisation does not match.

如果没有X的模板参数替换,则无法推导出Z.所以,专业化不匹配。

#2


1  

A<int> is int, so C<A, A<int>> is C<A, int>. The specialization cannot match what you want because it cannot see A<int>.

是int,因此C >是C 。专业化无法满足您的需求,因为它无法看到A ,int> ,a>

#3


1  

A is an alias template, and it essentially specializes to a typedef-name. A<int> is like a typedef for int *.

A是别名模板,它基本上专门用于typedef-name。 就像int *的typedef。

C<A, A<int>> is the same as C<A, int *>. The parameter X gets A and the parameter Y gets int *. To deduce that Z in the partial specialization should be int, the compiler would have to inspect inside the alias definition. That is not how aliases work. The definition is a non-deduced context, even if substituting the alias definition into its indirect use X<Z> in the partial specialization would produce a deduced context. Moreover, that deduction would need to be done speculatively to determine that A can even be X in the first place. Tackling this problem would be a huge burden of complexity.

C >与C 相同。参数X得到A,参数Y得到int *。为了推断部分特化中的Z应该是int,编译器必须在别名定义内部进行检查。这不是别名的工作方式。该定义是一个非推导的上下文,即使将别名定义替换为其间接使用,部分特化中的X 也会产生推导的上下文。此外,这种推论需要以推测的方式进行,以确定A首先甚至可以是X.解决这个问题将是一个巨大的复杂负担。 ,int> ,a>

As you mentioned on the std-discussion list, "An alias template name is never deduced."

正如您在std讨论列表中提到的那样,“永远不会推断出别名模板名称。”

#1


4  

I think that 14.5.7 Alias templates:

我认为14.5.7 Alias模板:

When a template-id refers to the specialization of an alias template, it is equivalent to the associated type obtained by substitution of its template-arguments for the template-parameters in the type-id of the alias template.

当template-id引用别名模板的特化时,它等同于通过替换别名模板的type-id中的template-parameters的template-arguments获得的关联类型。

would apply, so X<Z> would be interpreted as Z* as soon as X is known to be an alias template. The syntax for a partial specialisation does indeed use the template-id grammar rule. However, template argument substitution takes place as the last step in template argument deduction, only once all template arguments have been deduced.

将适用,因此只要知道X是别名模板,X 就会被解释为Z *。部分特化的语法确实使用了模板ID语法规则。但是,模板参数替换是模板参数推导的最后一步,只有在推导出所有模板参数后才会发生。

14.5.5.1 Matching of class template partial specializations [temp.class.spec.match]

14.5.5.1类模板部分特化的匹配[temp.class.spec.match]

2 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).

2如果可以从实际模板参数列表中推导出部分特化的模板参数,则部分特化匹配给定的实际模板参数列表(14.8.2)。

14.8.2 Template argument deduction [temp.deduct]

14.8.2模板参数推导[temp.deduct]

5 When all template arguments have been deduced or obtained from default template arguments, all uses of template parameters in the template parameter list of the template and the function type are replaced with the corresponding deduced or default argument values.

5当从默认模板参数推断或获得所有模板参数时,模板的模板参数列表中的模板参数的所有使用和函数类型将替换为相应的推导或默认参数值。

Without template argument substitution of X, Z cannot be deduced. So, the specialisation does not match.

如果没有X的模板参数替换,则无法推导出Z.所以,专业化不匹配。

#2


1  

A<int> is int, so C<A, A<int>> is C<A, int>. The specialization cannot match what you want because it cannot see A<int>.

是int,因此C >是C 。专业化无法满足您的需求,因为它无法看到A ,int> ,a>

#3


1  

A is an alias template, and it essentially specializes to a typedef-name. A<int> is like a typedef for int *.

A是别名模板,它基本上专门用于typedef-name。 就像int *的typedef。

C<A, A<int>> is the same as C<A, int *>. The parameter X gets A and the parameter Y gets int *. To deduce that Z in the partial specialization should be int, the compiler would have to inspect inside the alias definition. That is not how aliases work. The definition is a non-deduced context, even if substituting the alias definition into its indirect use X<Z> in the partial specialization would produce a deduced context. Moreover, that deduction would need to be done speculatively to determine that A can even be X in the first place. Tackling this problem would be a huge burden of complexity.

C >与C 相同。参数X得到A,参数Y得到int *。为了推断部分特化中的Z应该是int,编译器必须在别名定义内部进行检查。这不是别名的工作方式。该定义是一个非推导的上下文,即使将别名定义替换为其间接使用,部分特化中的X 也会产生推导的上下文。此外,这种推论需要以推测的方式进行,以确定A首先甚至可以是X.解决这个问题将是一个巨大的复杂负担。 ,int> ,a>

As you mentioned on the std-discussion list, "An alias template name is never deduced."

正如您在std讨论列表中提到的那样,“永远不会推断出别名模板名称。”