class 模板何时依赖不完整类型作为模板参数实例化?
When is a class template depending on a incomplete type as a template argument instantiated?
class I;
template<class T>
struct P
{
T t;
};
template<class T>
struct F
{
operator bool() {return false;}
};
int main()
{
int a = F<P<I>>();
int b = !F<P<I>>();
int c = int(F<P<I>>());
int d = !int(F<P<I>>());
}
上面的初始化器中的计算是否格式正确?为什么或者为什么不?标准中的哪些规则规定了行为?
只有在需要完整类型或影响给定上下文中的语义时,才会实例化特化。 [temp.inst]/2
因此默认行为是在不必要时不进行任何隐式实例化。
在您显示的所有情况下,需要实例化 F
的特化,因为 T()
需要 T
才能完成。但是F<P<I>>
的实例化中没有任何东西需要P<I>
来完成,所以不会用它来实例化。
None 到 int
的转换需要 P<I>
完成,因此 a
、c
和 [=19= 的初始化] 根本不会导致 P<I>
的任何实例化,它们是 well-formed.
但是,对于 b
,情况有点不同。为了确定要调用哪个 operator!
重载,已完成 operator!
的非限定名称查找和 argument-dependent 名称查找。
Argument-dependent 查找在与类型 F<P<I>>
.
相关的多个范围内查找 operator!
声明
首先,对于F
本身,它包括F
的class作用域和封闭的命名空间作用域,即全局作用域。但是,其次,它还在类型的模板参数中包括 class- 和封闭类型的命名空间范围,这意味着它也包括 P<I>
的 class 范围。
为了判断P<I>
中是否存在operator!
重载,必须对其进行实例化。在实例化 P<I>
时,声明 T t;
也被实例化为 I t;
,这需要 I
完成,但事实并非如此,使得 [=21= 的初始化] ill-formed.
但是 [temp.inst]/9 允许但不要求在不需要确定重载解析结果时跳过实例化。我不确定这个权限应该解释多宽,但如果它在这里适用,那么未指定 P<I>
的实例化是否发生 b
的初始化。
class I;
template<class T>
struct P
{
T t;
};
template<class T>
struct F
{
operator bool() {return false;}
};
int main()
{
int a = F<P<I>>();
int b = !F<P<I>>();
int c = int(F<P<I>>());
int d = !int(F<P<I>>());
}
上面的初始化器中的计算是否格式正确?为什么或者为什么不?标准中的哪些规则规定了行为?
只有在需要完整类型或影响给定上下文中的语义时,才会实例化特化。 [temp.inst]/2
因此默认行为是在不必要时不进行任何隐式实例化。
在您显示的所有情况下,需要实例化 F
的特化,因为 T()
需要 T
才能完成。但是F<P<I>>
的实例化中没有任何东西需要P<I>
来完成,所以不会用它来实例化。
None 到 int
的转换需要 P<I>
完成,因此 a
、c
和 [=19= 的初始化] 根本不会导致 P<I>
的任何实例化,它们是 well-formed.
但是,对于 b
,情况有点不同。为了确定要调用哪个 operator!
重载,已完成 operator!
的非限定名称查找和 argument-dependent 名称查找。
Argument-dependent 查找在与类型 F<P<I>>
.
operator!
声明
首先,对于F
本身,它包括F
的class作用域和封闭的命名空间作用域,即全局作用域。但是,其次,它还在类型的模板参数中包括 class- 和封闭类型的命名空间范围,这意味着它也包括 P<I>
的 class 范围。
为了判断P<I>
中是否存在operator!
重载,必须对其进行实例化。在实例化 P<I>
时,声明 T t;
也被实例化为 I t;
,这需要 I
完成,但事实并非如此,使得 [=21= 的初始化] ill-formed.
但是 [temp.inst]/9 允许但不要求在不需要确定重载解析结果时跳过实例化。我不确定这个权限应该解释多宽,但如果它在这里适用,那么未指定 P<I>
的实例化是否发生 b
的初始化。