C++高手请进 模板函数的调用困惑
Class Cat
{
};
template < typename T >
T* alloc()
{
return new T;
}
auto_ptr <Cat> pCat23( auto_ptr <Cat> ( alloc <Cat> () ) );
也并非使用时这样写,但是偶然的拼凑发现一个很令我困惑的问题,上面的代码不能编译成功,“error C2909: 'alloc ': explicit instantiation of template function requires return type”. 我的编译器是:visual studio 2003 7.1.3088
如果写成:
auto_ptr <Cat> pCat23( auto_ptr <Cat> ( new Cat ) );
就可以通过编译了,
请问哪位高手还能赐教?
[解决办法]
函数后面跟尖括号?我是没见过
像你这个函数貌似应该定义一个类然后重载它的函数调用运算符,做成仿函数形式
试试这个吧
template <typename T>
class Alloc
{
public:
T* operator ()(void){ return new T; }
}
Alloc <Cat> alloc;
auto_ptr <Cat> pCat23(alloc());
[解决办法]
class Cat
{
};
template < typename T >
T* alloc()
{
return new T;
}
int main()
{
auto_ptr <Cat> pCat23( auto_ptr <Cat> ( alloc <Cat> () ) );
system( "PAUSE ");
return 0;
}
Dev C++ 编译通过 。。。。。
[解决办法]
class Cat
{
};
template < typename T >
T* alloc()
{
return new T;
}
int main(int argc, char* argv[])
{
auto_ptr <Cat> pCat23( (auto_ptr <Cat> ( alloc <Cat> () )) ); <==应该是编译器解析的问题
return 0;
}
[解决办法]
这应该是VS2003的一个bug.
在这一行
auto_ptr <Cat> pCat23( auto_ptr <Cat> ( alloc <Cat> () ) );
中, 它把alloc <Cat> ()当成一个函数声明而不是函数调用. 编译器知道alloc之前已声明是一个模板函数,故此处的再声明在它看来就是显示特例化(explicit instantiation)了, 当然它是找不到返回值类型说明的(因为这儿压根就不是函数声明),如是就乎乎地报C2909号错误: explicit instantiation of template function requires return type
要饶开这个bug,我们可以多提供点信息给编译器,让它知道此处是函数调用.例如如下的两种方式都能通过编译:
auto_ptr <Cat> pCat23(auto_ptr <Cat> ((Cat*)alloc <Cat> () ) );
auto_ptr <Cat> pCat23((auto_ptr <Cat> )auto_ptr <Cat> (alloc <Cat> () ) );
二者都是加了一个类型强制转换,而且是 "转换 "到它自己的类型.通常这样作是毫无意义的,但在此处却是明白地告诉编译器:这是函数调用而不是声明(函数声明是不可能有类型cast的).
当然,最简单的解法还是如下方式:
auto_ptr <Cat> pCat23(alloc <Cat> () );
如blackmurder所说,楼主用的方式多了一个无谓的邻时变量.
VS2003号称对模板的支持很不错的.楼主的发现很有意思,呵呵.
[解决办法]
Effective STL item29给出了另外一个类似的例子
vector <char> v(istreambuf_iterator <char> (ifs), istreambuf_iterator <char> ());
必须写成
vector <char> v((istreambuf_iterator <char> (ifs)), istreambuf_iterator <char> ());
[解决办法]
显式实例化函数模板需要显式指定其返回类型。隐式指定返回类型无效。
[解决办法]
根据C++标准,在同等条件下,当可以解释为函数声明或对象声明(或定义)时,函数声明优先。
在这个例子中,
auto_ptr <Cat> pCat23( auto_ptr <Cat> ( alloc <Cat> () ) );
是可以被解释为函数声明的,它的正确形式是:
auto_ptr <Cat> pCat23( auto_ptr <Cat> ( Cat* alloc <Cat> () ) );
这里,函数pCat23的参数是 auto_ptr <Cat> ( Cat* alloc <Cat> () ),后者同样是一个函数声明,它的参数是 Cat* alloc <Cat> () ,后者同样是一个函数声明。
[注意了,可以直接使用函数声明作为一个函数的参数的,如:
int f();
int ff( int f() ); // 这是一个函数,它的参数是另一个函数(取其原型做为参数类型)。
]
而
auto_ptr <Cat> pCat23( auto_ptr <Cat> ( alloc <Cat> (1) ) );
auto_ptr <Cat> pCat23( auto_ptr <Cat> ((Cat*)alloc <Cat> () ) );
auto_ptr <Cat> pCat23( (auto_ptr <Cat> )auto_ptr <Cat> (alloc <Cat> () ) );
这三个例子都是对象定义,因为无法将alloc部分或auto_ptr <Cat> 部分解释成一个函数声明了。
至于
auto_ptr <Cat> pCat23(alloc <Cat> () );
需要考虑auto_ptr的构造函数原型,如下(VS2005中):
template <class _Ty>
class auto_ptr
{// wrap an object pointer to ensure destruction
public:
....
explicit auto_ptr(_Ty *_Ptr = 0) _THROW0()
auto_ptr(auto_ptr <_Ty> & _Right) _THROW0()
auto_ptr(auto_ptr_ref <_Ty> _Right) _THROW0()
....
};
观察构造函数的参数,可以发现alloc <Cat> 的返回值Cat*直接匹配第一个构造函数,因此将其解释为对象定义更合适。再看 auto_ptr <Cat> pCat23( auto_ptr <Cat> ( alloc <Cat> () ) ); 的例子,没有直接匹配的构造函数;因此同等条件下,解释为函数声明更合适。
以上仅个人意见,供参考。