C ++语法调用模板化内部类的静态成员函数?

时间:2010-01-19 07:32:04

标签: c++ macos templates gcc

我有一些模板代码可以在VC9(Microsoft Visual C ++ 2008)中编译好,但不能在GCC 4.2(在Mac上)编译。我想知道是否有一些我缺少的语法魔法。

下面我有一个精简的示例,演示了我的错误。对不起,如果这个例子看起来毫无意义,我尽可能地删除了这个错误。

特别是我有一个模板类S,它有一个内部类R,它也是一个模板类。从顶级模板函数foo,我试图调用R :: append这是R的静态成员函数:

template< typename C >
struct S {
    template< typename T >
    S<C> & append( const T & ) { return *this; }

    template< int B >
    struct R {
        template< typename N >
        static S<C> & append( S<C> & s, const N ) {
            return s.append( 42 );
        }
    };
};

template< typename C >
S<C> & foo( S<C> & s, const int n ) {
    S<C>::R<16>::append( s, n ); // error: '::append' has not been declared
    return s;
}

那里的任何人都知道我做错了什么?

4 个答案:

答案 0 :(得分:4)

我用它来编译:

template< typename C >
S<C> & foo( S<C> & s, const int n ) {
    typedef typename S<C>::template R<16> SR;
    SR::append( s, n );
    return s;
}

答案 1 :(得分:4)

您必须告诉编译器,从属名称R是一个模板:

template< typename C >
S<C> & foo( S<C> & s, const int n ) {
    S<C>::template R<16>::append( s, n );
    return s;
}

答案 2 :(得分:2)

同时使用Visual Studio和gcc,这是一个已知的问题:)我使用了VS2003和gcc 3.4.2所以它已经有一段时间了。

如果我没记错的话,问题是由于在这些编译器上解析模板的方式。

gcc的行为与标准相同,并执行2次解析:

  • 第一次遇到模板时,没有关于类型的任何信息,此时需要一些typenametemplate魔术来帮助理解正在发生的事情
  • 实际使用给定类型
  • 实例化模板时的第二个
另一方面,VS在实例化时只进行一次解析,因此可以在此处和那里完全解析没有typenametemplate的符号。

你对方法有同样的看法:

template <class Item>
struct Test
{
  template <class Predicate>
  void apply(Predicate pred);

  void doSomething { this->apply(MyPredicate()); }          // Visual Studio
  void doSomething { this->template apply(MyPredicate()); } // gcc
}; // struct Test

在同一主题上,如果您执行以下操作:

template <class Item>
struct Test { static const std::string Name; };

您需要为模板的每个实例化实际定义此static属性,否则您将拥有未定义的符号。

VS接受这种语法:

const std::string Test<MyType>::Name = "MyType";

但是gcc要求一个小关键字:

template <> const std::string Test<MyType>::Name = "MyType";

你可能会认为VS更好,因为它要求你少,但另一方面,gcc可能会在你第一次解析它们时(即没有任何实际的实例化)警告你模板方法/类中的错误而且就个人而言,越快越好。

显然,好消息是如果在gcc上编译(对于这些问题),它也可以在Visual Studio上正常编译。

由于我不是标准人,但我不确定该标准是否实际要求或建议2-parses方案。

答案 3 :(得分:0)

尝试在struct R :: append中编写“const int N”,然后使用N(而不是42?)。