2011-12-18 114 views
1

关于模板实例化和继承,我一直面临着一个很大的挑战(至少对我而言)。让我们来看看下面的代码:C++模板挑战

class Convertible 
{ 
    public: 

    template<class T> 
    T* AsPtrTo() 
    { 
     return reinterpret_cast<T*>(this); 
    } 
}; 

template<class T> 
class TemplateBase : public Convertible 
{ 
}; 

template<class T> 
class TemplateDerived : public TemplateBase<T> 
{ 
    public: 

    void Method1(TemplateBase<T> t) 
    { 
     t.AsPtrTo<int>(); // <<<<<< ERROR 
    } 
}; 


int main() 
{ 
    TemplateDerived<int> d; 
    TemplateBase<int> b; 
    d.Method1(b); 

    return 0; 
} 

正如你所看到的,还有一类,称为转换,与执行一个类型转换只是一个模板方法。还有一个从Convertible继承的模板类,然后是从前一个继承的另一个模板类。最后一个模板类实现了一个方法,该方法使用模板方法AsPtrTo,该方法在编译期间应该从Convertible继承,并在编译期间用于主函数中的类型T.

由于某种原因,我不明白,这失败了。 GCC 4.4.1给我这个消息:

error: expected primary-expression before 'int'

我已经标记了错误的行。

我想也许这里的一位C++专家可以帮我一把。

谢谢大家提前!

+0

“'return reinterpret_cast (this)''你不是那么做,是吗? – curiousguy 2011-12-19 05:49:14

回答

6

您需要使用关键字template为:

t.template AsPtrTo<int>(); 

这已被讨论过很多次,你会发现在SO帖子不计其数的。

但在这里,你会找到最好的解释之一:

+1

感谢您的回答,我搜索了与此相关的帖子,但找不到任何内容:(当然,我使用了错误的关键字。问题现在已经清楚了,再次感谢。 – Thund 2011-12-18 15:32:24

4

尝试:

void Method1(TemplateBase<T> t) 
{ 
    t.template AsPtrTo<int>(); 
} 

的原因是,编译器不知道是什么的成员函数t具有解析时间,所以它不知道AsPtrTo是否是模板函数。正因为如此,没有提示就无法正确解析它。

至于为什么这是需要一个例子,考虑下面的代码:

struct Foo 
{ 
    template<int N> int foo(int x) { return x + N; } 
}; 

struct Bar 
{ 
    int foo; 
}; 

template <typename T> 
int baz(T t) 
{ 
    return t.foo<0>(1); 
} 

一目了然,它看起来像baz<Foo>将工作,但baz<Bar>不会,但它是倒过来!

考虑一下,如果我叫baz<Bar>

return t.foo<0>(1);

foo是一个成员变量,所以当它看到它认为它的<会发生什么小于操作,所以它解析像这样的表达:

return (t.foo < 0) > (1);

这是一个有效的表达式(一些隐式转换到/从后)!

问题是,它会对FooBar这两个表达式进行解析,这就是为什么需要template关键字的原因。编译器必须假定它不是模板成员函数(除非你把那个关键字放在那里)。