[英]Compiler errors on partial template speciailzation (c++)
I am trying to do a simple partial template specialization, but I get errors on g++4.4.7, g++4.8.5, clang++3.8.0. 我试图做一个简单的局部模板专门化,但是在g ++ 4.4.7,g ++ 4.8.5,clang ++ 3.8.0上出现错误。 Whenever I mention compiler(s) error, I mean the output of all of these, as they always agree. 每当我提到编译器错误时,我都是指所有这些的输出,因为它们总是一致的。 I am using C++03, compiling without any option. 我正在使用C ++ 03,没有任何选择地进行编译。
The code: 编码:
#include <iostream>
template <typename T, typename X, typename G>
struct A {};
template <typename T, typename X>
struct A<T, X, void> { A() : n(1) {} X n; T b; };
template <typename X>
struct A<X, void, void> { A() : n(2) {} X n; };
int main() {
A<int, float> one;
A<int> two;
std::cout << one.n << " | " << two.n << "\n";
return 0;
}
Question 1: This code fails to compile. 问题1:此代码无法编译。 The compilers say that A<int, float>
and A<int>
are wrong as A
requires 3 templates parameters. 编译器说A<int, float>
和A<int>
是错误的,因为A
需要3个模板参数。 Why? 为什么?
If I change the original declaration to 如果我将原始声明更改为
template <typename T, typename X = void, typename G = void>
struct A {};
The code compiles and the output is: 1 | 2
代码经过编译,输出为: 1 | 2
1 | 2
. 1 | 2
。
What happens is that the compiler in a first step matches one
and two
type to the not specialized A
, but then it correctly decides to use the code of the partially specialized class one would expect it to use. 发生的情况是,编译器首先将one
类型和two
类型与未专用的A
匹配,但是随后它正确地决定使用希望使用的部分专用类的代码。 But it should not need the defaults. 但是它不需要默认值。
I then decide to change the last partial specialization switching the first and second parameter: 然后,我决定更改第一个和第二个参数,以更改最后的部分专业化:
template <typename X>
struct A<void, X, void> { A() : n(2) {} X n; };
I would expect this to change nothing, but the compilers disagree. 我希望这不会改变任何东西,但是编译器不同意。 The clearest output between the 3 is here reported: 此处报告了这3个之间最清晰的输出:
a.cpp:7:40: error: field has incomplete type 'void'
struct A<T, X, void> { A() : n(1) {} X n; T b; };
^
a.cpp:14:10: note: in instantiation of template class 'A<int, void, void>' requested here
A<int> two;
^
1 error generated.
Question 2: Why are the compilers considering the two
variable an instance of the partial specialization of A that specializes only one argument? 问题2:为什么编译器将two
变量视为A的部分专业化实例的一部分,该实例仅专门化一个参数?
Note that is the "2nd matching", because if I only use 1 default template argument, the compiler will go back to complaining about the fact that 3 template parameters are needed. 请注意,这是“第二次匹配”,因为如果我仅使用1个默认模板参数,则编译器将回过头来抱怨需要3个模板参数这一事实。
Thanks. 谢谢。
Question 1: This code fails to compile. 问题1:此代码无法编译。 The compilers say that
A<int, float>
andA<int>
are wrong asA
requires 3 templates parameters. 编译器说A<int, float>
和A<int>
是错误的,因为A
需要3个模板参数。 Why? 为什么?
Because A
requires 3 template parameters. 因为A
需要3个模板参数。 You declared A
as: 您将A
声明为:
template <typename T, typename X, typename G>
struct A {};
There is no two- or one-template parameter version of A
. 有没有二维或一模板参数版本的A
。 There are versions specialized on some of the types being void
, but that's still a parameter - not an absence of parameter. 有一些版本专门针对某些类型为void
的类型,但这仍然是一个参数-并非缺少参数。
When you add the defaults, then A<int, float>
evaluates as A<int, float, void>
, which is a valid instantiation - and picks the specialization which sets n
to 1. 添加默认值后, A<int, float>
计算结果为A<int, float, void>
,这是有效的实例化-并选择将n
设置为1的特殊化。
You're misunderstanding how specialization works. 您误会了专业化的工作原理。 Specialization doesn't change the number of template parameters. 专业化不会更改模板参数的数量。 It's just a way of adding special functionality depending on what the template parameters end up being. 这只是根据最终模板参数添加特殊功能的一种方式。
Question 2: Why are the compilers considering the two variable an instance of the partial specialization of
A
that specializes only one argument? 问题2:为什么编译器将两个变量视为A
的部分专业化实例的一部分,该实例仅专门化一个参数?
We have three choices 我们有三个选择
template <T, X, G> struct A; // the primary
template <T, X, void> struct A; // (1)
template <void, X, void> struct A; // (2)
When we instantiate A<int>
, that is the same as A<int, void, void>
when we add in the default parameters. 实例化A<int>
,与添加默认参数时的A<int, void, void>
相同。 That does not match (2)
- because that one requires the first parameter to be void
and yours is int
. 那不匹配(2)
-因为那个要求第一个参数为void
并且您的参数为int
。 (1)
is a better match than the primary since it's more specialized. (1)
比主要版本更好,因为它更专业。 But then, (1)
has a member of type X
and in this case X
is deduced as void
(from the default parameter), and that's not allowed. 但是, (1)
具有类型X
的成员,在这种情况下, X
被推导为void
(从默认参数),这是不允许的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.