我做了以下计划
#include <iostream>
#include <typeinfo>
template<class T>
struct Class
{
template<class U>
void display(){
std::cout<<typeid(U).name()<<std::endl;
return ;
}
};
template<class T,class U>
void func(Class<T>k)
{
k.display<U>();
}
int main()
{
Class<int> d;
func<int,double>(d);
}
上述程序无法编译,因为display()
是模板成员函数,因此必须在.template
之前完成display()
的限定。我是对的吗?
但是当我制作以下节目时
#include <iostream>
#include <typeinfo>
template<typename T>
class myClass
{
T dummy;
/*******/
public:
template<typename U>
void func(myClass<U> obj);
};
template<typename T>
template<typename U>
void myClass<T>::func(myClass<U> obj)
{
std::cout<<typeid(obj).name()<<std::endl;
}
template<class T,class U>
void func2(myClass<T>k)
{
k.template func<U>(k); //even it does not compile
}
int main()
{
myClass<char> d;
func2<char,int>(d);
std::cin.get();
}
为什么k.func<char>(k);
即使在给出.template
构造后也无法编译?
答案 0 :(得分:19)
<
符号表示“小于”和“开始模板参数”。为了区分这两个含义,解析器必须知道前面的标识符是否命名模板。
例如,考虑代码
template< class T >
void f( T &x ) {
x->variable < T::constant < 3 >;
}
T::variable
或T::constant
必须是模板。该函数意味着不同的东西取决于哪个,哪个不是:
T::constant
与3进行比较,布尔结果成为T::variable<>
的模板参数T::constant<3>
与x->variable
进行比较。要消除歧义,template
或variable
之前需要constant
关键字。案例1:
template< class T >
void f( T &x ) {
x->template variable < T::constant < 3 >;
}
案例2:
template< class T >
void f( T &x ) {
x->variable < T::template constant < 3 >;
}
如果关键字仅在实际模糊的情况下需要(这种情况很少见)会很好,但它会使解析器更容易编写,并且可以防止这些问题让您感到意外。
关于标准,见14.2 / 4:
当成员模板的名称时 专业化之后出现。或 - &gt; 在后缀表达式中,或之后 a中的嵌套名称说明符 qual-id和 postfix-expression或qualified-id 明确取决于a template-parameter(14.6.2),. 成员模板名称必须加前缀 通过关键字模板。否则 假定名称命名为 非模板。
答案 1 :(得分:7)
C++ Templates的第5.1节详细解释了这个结构
以下功能有问题
template<class T,class U>
void func2(myClass<T> k)
{
k.template func<U>(k); //even it does not compile
}
这里T = char,U = int
myclass<char>::func<int>(myclass<char>)
正在呼叫。但是这样的功能不存在
即使在正常情况下'char'可以转换为'int',但这对于明确指定的模板参数不起作用
答案 2 :(得分:0)
该标准要求template
或typename
个关键字disambiguate things that depend on the template context。
答案 3 :(得分:0)
第一个例子在VS 2010中编译并运行正常。