C ++ syntax for calling a template function of a static member of an inner class?

I have template code that compiles in VC9 (Microsoft Visual C ++ 2008) but will not compile in GCC 4.2 (on Mac). I am wondering if there is some kind of syntactic magic that I am missing.

Below is a stripped down example demonstrating my mistake. Sorry if this example seems pointless, I deleted as much as possible to isolate this error.

In particular, I have a template class S that has an inner class R, which is also a template class. From the top-level template function foo, I am trying to call R :: append, which is a static member function of 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; } 

Does anyone know what I'm doing wrong?

+4
source share
4 answers

Using both Visual Studio and gcc is a known issue :) And I used VS2003 and gcc 3.4.2, so it was a while.

If I remember correctly, the problem is related to the way the patterns are analyzed on these compilers.

gcc behaves as specified by the standard and performs 2 parses:

  • the first, when it encounters a template, without any type information, at that moment several magicians typename and template required to help understand what is happening
  • second when the template instance with the specified type is actually created

on the other hand, VS does only one parsing at instantiation and therefore can fully resolve characters without typename and template here and there.

You have the same 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 

In the same topic, if you are doing something like:

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

You need to define this static attribute for each instance of the template, or you will have an undefined character.

VS accepts this syntax:

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

But gcc asks for a little keyword:

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

You can think of VS as the best, as it asks you less, but, on the other hand, gcc can warn you about errors in your template methods / classes as soon as it analyzes them for the first time (i.e. without any actual instantiation) and personally, the sooner the better.

Obviously, the good news is that if compiling on gcc (for these problems), it will also compile in Visual Studio.

Since I'm not standardized, I'm not sure if the standard really requires or recommends a 2-pars scheme.

+2
source

I can compile it 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; } 
+4
source

You must tell the compiler that the dependent name R is a pattern:

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

Try writing "const int N" in struct R :: append, and then use N (rather than 42?).

0
source

All Articles