2010-01-19 72 views
6

我有与VC9(Microsoft Visual C++ 2008 SP1)编译良好的代码,但与GCC 4.2(在Mac上,如果重要的话)不能。如果我在足够的限定词和关键字上堆积,我可以强制它在GCC中工作,但这看起来不正确。模板基类typedefs和函数的更好的C++语法?

下面是一个最小的代码示例展示我的问题:

template< typename N > 
struct B { 
    typedef N n_type;      // can derived class access typedef? 
    void foo() {}       // can derived class access function? 
}; 

template< typename N > 
struct D : public B<N> { 

    typedef B<N> b_type; 
    typedef typename b_type::n_type bn_type; 

    void f1(n_type) {}     // ERROR: 'n_type' has not been 
              // declared 

    void f2(typename B<N>::n_type) {} // OK, verbose 

    void f3(b_type::n_type) {}   // ERROR: 'struct B<N>::n_type' is 
              // not a type 

    void f4(typename b_type::n_type) {} // OK, verbose 

    void f5(bn_type) {}     // OK, verbose typedefs 

    void f6() { foo(); }     // ERROR: there are no arguments to 
              // 'foo' that depend on a template 
              // parameter, so a declaration of 
              // 'foo' must be available 

    void f7() { b_type::foo(); }   // OK, verbose 

}; 

我错了期待从另一个模板类派生的模板类是能够直接使用继承的typedef和功能呢?有没有比迄今为止我想出的更好的方式来做到这一点?

+0

什么'的typedefñn_type'点?你可以直接使用'N' – Trent 2010-01-19 16:58:50

+3

typedef不是继承的,Visual C++经常不符合标准。可以使用作用域分辨率IE base :: f或this-> f访问继承的函数。你也可以使用“using base :: f”将函数带入本地作用域。 – Anycorn 2010-01-19 17:06:04

+0

它适用于我,除了f3的情况。 – 2010-01-19 17:14:59

回答

9

我错了,期望从另一个模板类派生的模板类能够直接使用继承的typedefs和函数吗?

是的,这通常不会像你期望的那样工作。 C++名称查找规则指定仅在模板化基类中搜索名称(如果它依赖于模板参数)(如果它是“依赖名称”)。如果名称不依赖于模板参数,则不在该处搜索。 (另见this C++ FAQ Lite entry

要从依赖基类的最简单的方法是使用this->调用函数,因为this总是隐含一个从属名称:

void f6() { this->foo(); } 
+1

'这个'对'n_type'没有帮助,但是哦,那就是它的样子。 – ephemient 2010-01-19 17:21:53

+1

你可以添加'typedef typename B :: n_type n_type;'得到一个类型'n_type',它指的是正确的东西,但也许最好在那里显式。 – sth 2010-01-19 17:32:02

2

没有类型n_type。有(或可能是)一个类型的名称取决于N.所以不,你不能做你想要的。

3

查看C++ FAQ Lite § 35.18-20C++ Templates FAQ

两阶段名称查找是C++的一个棘手部分,许多编译器(和编码器)出错了。可以这么说,GCC比MSVC更正确(按照C++规范),并且不,没有更好的方法来做你想做的事情。