面试题答案
一键面试- 实例化
Outer<int, double>
:- 编译器首先查找
Outer
模板的定义。它会从通用模板定义开始找起,即template <typename T1, typename T2> class Outer
。 - 然后检查是否存在
Outer<int, double>
的全特化。如果存在template <> class Outer<int, double>
的全特化定义,编译器将使用这个全特化定义;如果不存在全特化,则使用通用模板定义。
- 编译器首先查找
- 实例化
Outer<int, double>::Inner<float>
:- 当编译器确定了
Outer<int, double>
的定义后,开始查找Inner
模板的定义。 - 对于
Inner
模板,同样先从通用模板定义template <typename U> class Inner
找起。 - 接着检查是否存在
Outer<int, double>::Inner
针对float
的特化。如果存在template <> class Outer<int, double>::Inner<float>
的特化定义,编译器将使用这个特化定义;如果不存在,则使用通用模板定义。
- 当编译器确定了
- 模板参数推导:
- 在这个过程中,
Outer
模板的参数T1
被推导为int
,T2
被推导为double
。 - 对于
Inner
模板,参数U
被推导为float
。
- 在这个过程中,
- 特化匹配:
- 编译器按照从最特化到最通用的顺序进行匹配。对于
Outer
,先找全特化,再用通用模板;对于Inner
,先找部分特化(如果有针对特定外层模板参数组合下的特化),再找通用模板。
- 编译器按照从最特化到最通用的顺序进行匹配。对于
- 可能出现的歧义及解决:
- 歧义情况:
- 可能存在多个部分特化都匹配
Outer<int, double>::Inner<float>
的情况。例如,假设有template <typename U> class Outer<int, double>::Inner<U>
和template <> class Outer<int, double>::Inner<float>
,这种情况下会出现歧义。 - 也可能在查找
Outer
或Inner
模板时,有多个定义都看似匹配(比如不同命名空间下有相似的模板定义)。
- 可能存在多个部分特化都匹配
- 解决方法:
- 对于多个部分特化匹配的情况,C++ 标准规定最特化的模板优先。如果多个部分特化的特化程度相同,编译器会报错。程序员可以通过修改特化定义,使其特化程度有明显区分来解决。
- 对于不同命名空间下相似模板定义的歧义,通过明确指定命名空间,如
namespaceA::Outer<int, double>::Inner<float>
,来让编译器明确使用哪个模板定义。
- 歧义情况: