模板模板参数的偏特化问题:两类特化版本编译报错原因解析
模板特化编译错误原因解析
先看我们定义的模板类及特化代码:
template< typename C > class B { public: void inc( C & x ) { ++x; } }; template< template< typename > typename A , typename C > class One { C a{}; void inc( void ) { A< C >::inc( a ); } }; // 版本一 template< template< typename > typename , typename C > class One< B< C > , C > { void inc2( void ) { inc(); inc(); } }; // 版本二 template< typename C > class One< B , C > { void inc2( void ) { inc(); inc(); } }; int main(){ One< B<int>, int> _one; One< B, int> _two; }
场景1:注释版本二时的编译错误
编译报错信息:
error: template argument for template template parameter must be a class template or type alias template class One< B< C > , C > {
错误原因
主模板One的第一个参数是模板模板参数(template< typename > typename A),它要求传入的是类模板本身(比如B),而非模板实例化后的具体类类型(比如B<C>)。
版本一的特化尝试用B<C>作为One的第一个模板参数,但B<C>是已经完成实例化的具体类,不符合模板模板参数的要求,因此编译器报错提示参数类型不匹配。
场景2:注释版本一时的编译错误
编译报错信息:
error: use of undeclared identifier 'inc'; did you mean 'inc2'? void inc2( void ) { inc(); inc(); } ^~~ inc2
错误原因
- 版本二的特化
One<B, C>是针对主模板的合法特化(B是模板模板参数的合法输入),但这个特化类是完全独立的定义,不会自动继承主模板的成员函数inc()。因此在inc2()中调用inc()时,编译器找不到该标识符,从而报错。 One<B, C>和One<B<int>, int>不存在特化关系:前者的第一个参数是类模板B,后者的第一个参数是具体类B<int>,二者的模板参数类别完全不同,编译器会将它们视为完全独立的模板实例,而非特化与被特化的关系。
内容的提问来源于stack exchange,提问作者Daniele Caliandro
相关产品推荐
相关产品推荐

