[英]Compiler errors on partial template speciailzation (c++)
我试图做一个简单的局部模板专门化,但是在g ++ 4.4.7,g ++ 4.8.5,clang ++ 3.8.0上出现错误。 每当我提到编译器错误时,我都是指所有这些的输出,因为它们总是一致的。 我正在使用C ++ 03,没有任何选择地进行编译。
编码:
#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;
}
问题1:此代码无法编译。 编译器说A<int, float>
和A<int>
是错误的,因为A
需要3个模板参数。 为什么?
如果我将原始声明更改为
template <typename T, typename X = void, typename G = void>
struct A {};
代码经过编译,输出为: 1 | 2
1 | 2
。
发生的情况是,编译器首先将one
类型和two
类型与未专用的A
匹配,但是随后它正确地决定使用希望使用的部分专用类的代码。 但是它不需要默认值。
然后,我决定更改第一个和第二个参数,以更改最后的部分专业化:
template <typename X>
struct A<void, X, void> { A() : n(2) {} X n; };
我希望这不会改变任何东西,但是编译器不同意。 此处报告了这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.
问题2:为什么编译器将two
变量视为A的部分专业化实例的一部分,该实例仅专门化一个参数?
请注意,这是“第二次匹配”,因为如果我仅使用1个默认模板参数,则编译器将回过头来抱怨需要3个模板参数这一事实。
谢谢。
问题1:此代码无法编译。 编译器说
A<int, float>
和A<int>
是错误的,因为A
需要3个模板参数。 为什么?
因为A
需要3个模板参数。 您将A
声明为:
template <typename T, typename X, typename G>
struct A {};
有没有二维或一模板参数版本的A
。 有一些版本专门针对某些类型为void
的类型,但这仍然是一个参数-并非缺少参数。
添加默认值后, A<int, float>
计算结果为A<int, float, void>
,这是有效的实例化-并选择将n
设置为1的特殊化。
您误会了专业化的工作原理。 专业化不会更改模板参数的数量。 这只是根据最终模板参数添加特殊功能的一种方式。
问题2:为什么编译器将两个变量视为
A
的部分专业化实例的一部分,该实例仅专门化一个参数?
我们有三个选择
template <T, X, G> struct A; // the primary
template <T, X, void> struct A; // (1)
template <void, X, void> struct A; // (2)
实例化A<int>
,与添加默认参数时的A<int, void, void>
相同。 那不匹配(2)
-因为那个要求第一个参数为void
并且您的参数为int
。 (1)
比主要版本更好,因为它更专业。 但是, (1)
具有类型X
的成员,在这种情况下, X
被推导为void
(从默认参数),这是不允许的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.