[英]Why does the following code cause the template instantiation?
I have the following C++ code: 我有以下C ++代码:
//Define to 1 to make it work
#define WORKS 0
#if WORKS
template< typename T > struct Foo;
#else
template< typename T >
struct Foo {
T t;
};
#endif
class Bar; //Incomplete type
void fFooBar(Foo<Bar> const & foobar) { }
void f(Foo<Bar> const & foobar) {
fFooBar(foobar);
}
int main() {
return 0;
}
If WORKS is defined as 0 (the struct template is defined) the code doesn't compile, because it tries to instantiate it at fFooBar(foobar);
如果WORKS被定义为0(定义了结构模板),则代码不会编译,因为它试图在
fFooBar(foobar);
实例化它fFooBar(foobar);
and fails, because Bar
is incomplete. 并且失败了,因为
Bar
不完整。
If WORKS is defined as 1 (the struct template is undefined) the code compiles. 如果WORKS定义为1(结构模板未定义),则代码将编译。
According to the standard, a template should not be instatiated, unless a complete type is required (which is not the case for const&
) or it would alter the semantics of the code (which again isn't the case, and againt, the same should happen if the template was undefined). 根据标准,模板不应该被实例化,除非需要一个完整的类型(
const&
不是这种情况)或者它会改变代码的语义(情况也不是这样,并且同样,相同)如果模板未定义,应该会发生)。
Also, it's weird that the program can be made to compile by removing information from the compilation unit. 而且,通过从编译单元中删除信息可以使程序编译,这很奇怪。 But the fact that MSVC, gcc, and clang all do the same makes me think there must be a reason behind this.
但MSVC,gcc和clang都这样做的事实让我觉得必须有这背后的理由。
When WORKS=0
, the program can be made to compile in Clang by qualifying the call to fFooBar
with ::
. 当
WORKS=0
,可以通过使用::
限定对fFooBar
的调用,使程序在Clang中编译。 The standard requires that name lookup behaves differently when an unqualified name is used in a function call. 该标准要求在函数调用中使用非限定名称时,名称查找的行为会有所不同。
[basic.lookup.argdep]/1
[basic.lookup.argdep] / 1
When the postfix-expression in a function call (5.2.2) is an unqualified-id, other namespaces not considered during the usual unqualified lookup (3.4.1) may be searched, and in those namespaces, namespace-scope friend function declarations (11.3) not otherwise visible may be found.
当函数调用(5.2.2)中的postfix-expression是非限定id时,可以搜索在通常的非限定查找(3.4.1)期间未考虑的其他名称空间,并在这些名称空间中搜索名称空间范围的朋友函数声明( 11.3)可能没有其他可见的。
Examining the (somewhat complex) rules for the Argument Dependent Lookup process suggests that it can only be implemented correctly in a way that would require the instantiation of template specialisations in the types of the arguments to the call. 检查Argument Dependent Lookup过程的(有点复杂的)规则表明它只能以需要在调用参数类型中实例化模板特化的方式正确实现。
[basic.lookup.argdep]/2
[basic.lookup.argdep] / 2
For each argument type T in the function call, there is a set of zero or more associated namespaces and a set of zero or more associated classes to be considered.
对于函数调用中的每个参数类型T,存在一组零个或多个关联的命名空间以及要考虑的一组零个或多个关联的类。 The sets of namespaces and classes is determined entirely by the types of the function arguments [...]
命名空间和类的集合完全由函数参数的类型决定[...]
- If T is a class type (including unions), its associated classes are: the class itself;
如果T是类类型(包括联合),则其关联的类是:类本身; the class of which it is a member, if any;
它所属的成员,如果有的话; and its direct and indirect base classes.
及其直接和间接基类。
One interpretation of this is that a class is required to be complete if it is used in the type of an argument to an unqualified function call. 对此的一种解释是,如果在非限定函数调用的参数类型中使用类,则该类必须是完整的。 An alternative interpretation is that ADL should only cause instantiation of templates that are complete.
另一种解释是ADL应该只导致完整模板的实例化。
Either behaviour is compliant with the standard according to Working Draft N3337 根据N3337工作草案,这两种行为都符合标准
[temp.inst]/6
[temp.inst] / 6
If the overload resolution process can determine the correct function to call without instantiating a class template definition, it is unspecified whether that instantiation actually takes place.
如果重载解析过程可以在不实例化类模板定义的情况下确定要调用的正确函数,则未指定该实例化是否实际发生。
template <class T> struct S {
operator int();
};
void f(int);
void f(S<int>&);
void f(S<float>);
void g(S<int>& sr) {
f(sr); // instantiation of S<int> allowed but not required
// instantiation of S<float> allowed but not required
};
[temp.inst]/7
[temp.inst] / 7
If an implicit instantiation of a class template specialization is required and the template is declared but not defined, the program is ill-formed.
如果需要隐式实例化类模板特化并且声明模板但未定义模板,则程序格式错误。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.