简体   繁体   English

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

[英]C++ syntax to call templated inner class static member function?

I have some template code which compiles fine in VC9 (Microsoft Visual C++ 2008) but won't compile in GCC 4.2 (on Mac). 我有一些模板代码可以在VC9(Microsoft Visual C ++ 2008)中编译好,但不能在GCC 4.2(在Mac上)编译。 I'm wondering if there's some syntactical magic that I'm missing. 我想知道是否有一些我缺少的语法魔法。

Below I have a stripped-down example which demonstrates my error. 下面我有一个精简的示例,演示了我的错误。 Sorry if this example seems meaningless, I removed as much as I could to isolate this error. 很抱歉,如果这个例子看起来毫无意义,我尽可能地删除了这个错误。

In particular I have a template class S which has an inner class R which is also a template class. 特别是我有一个模板类S,它有一个内部类R,它也是一个模板类。 From a top-level template function foo, I am trying to call R::append which is a static member function of 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;
}

Anyone out there know what I'm doing wrong? 那里的任何人都知道我做错了什么?

I get it to compile with: 我得到它编译:

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;
}

You have to tell the compiler that the dependent name R is a template: 您必须告诉编译器依赖名称R是模板:

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

Having use both Visual Studio and gcc, it's a known issue :) And I used VS2003 and gcc 3.4.2 so it's been like that for a while. 同时使用Visual Studio和gcc,这是一个已知问题:)我使用了VS2003和gcc 3.4.2所以它已经有一段时间了。

If I remember correctly, the problem is due to the way templates are parsed on these compilers. 如果我没记错的话,问题是由于在这些编译器上解析模板的方式。

gcc behaves as stated by the standard, and performs 2 parses: gcc的行为与标准相同,并执行2次解析:

  • the first when encountering the template, without any information on the types, at this point it necessitates some typename and template magic to help understand what's going on 第一次遇到模板时,没有关于类型的任何信息,此时需要一些typenametemplate magic来帮助理解发生了什么
  • a second when actually instantiating the template with a given type 实际使用给定类型实例化模板时的第二个

on the other hand, VS only does one parse, at instantiation, and therefore can fully resolve the symbols without typename and template here and there. 另一方面,VS在实例化时只进行一次解析,因此可以完全解析没有typenametemplate的符号。

You have the same thing for methods: 你对方法有同样的看法:

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

On the same topic, if you do something like: 在同一主题上,如果您执行以下操作:

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

You need to actually define this static attribute for each instantiation of the template, or you'll have an undefined symbol. 您需要为模板的每个实例化实际定义此static属性,否则您将拥有未定义的符号。

VS accepts this syntax: VS接受以下语法:

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

But gcc asks for a little keyword: 但是gcc要求一个小关键字:

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

You may think of VS as better since it asks less of you, but on the other hand gcc may warn you of mistakes in your template methods / classes as soon as it parses them the first time (ie without any actual instantiation) and personally, the sooner the better. 您可能会认为VS更好,因为它要求您少一些,但另一方面,gcc可能会在您第一次解析模板方法/类时(即没有任何实际实例化)并在个人情况下警告您模板方法/类中的错误越快越好。

Obviously, the good news is that if compiles on gcc (for these issues), it will also compile fine on Visual Studio. 显然,好消息是如果在gcc上编译(对于这些问题),它也可以在Visual Studio上编译好。

Since I am not a standardista though, I am not sure whether or not the standard actually demands or advises the 2-parses scheme. 由于我不是标准的,我不确定标准是否实际要求或建议2-parses方案。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM