在使用Microsoft VisualStudio 2008构建一个小的示例程序时,我注意到有关传递给模板的类型推断的奇怪事情。考虑以下示例:
template<class T>
void f( T v ) {
x; // trigger a compile error
(void)v;
}
template<class T>
void g( T v ) {
f( v );
}
void h() {
int i;
g<const int &>( i );
}
使用cl /c foo.cpp
编译此示例会导致编译错误(这是预期的)。有趣的是'T'模板参数的值。以下是VisualStudio 2008打印的内容:
mini.cpp(3) : error C2065: 'x' : undeclared identifier
mini.cpp(9) : see reference to function template instantiation 'void f<int>(T)' being compiled
with
[
T=int
]
mini.cpp(14) : see reference to function template instantiation 'void g<const int&>(T)' being compiled
with
[
T=const int &
]
请注意,在函数
g
中,参数的类型是 const int &
,但在函数 f
中,它只是一个普通的 int
类型。显然,在推断实例化 f
模板时使用的类型时,对于引用到常量的部分进行了剥离。当调整示例以使 f
被调用时,请注意这一点。f<T>( v );
f
和g
中的类型都是const int &
。为什么会这样?这是指定的行为吗?我曾经暗自依赖于传递给f
的v
函数参数的类型,但显然不是。
f
模板中触发编译错误,因为 GCC 正确地进行了两阶段编译。x
不依赖于模板参数,所以应该在第一阶段被拒绝(如 GCC 中),而不是在第二阶段(如 MSVC 中)。但是将x
更改为v = 1;
,很容易看出,除非你在g
中显式指定f<T>(v)
,否则 GCC 不会使用const int&
实例化f
。 - Steve Jessop