Question

My problem can be resumed by the following piece of code:

template <typename T> struct C2;

template <typename T> 
struct C1
{
  template <typename Type,
        template <typename Ti> class Container = C2>
  void m() {}
};


template <typename T> 
struct C2
{
  template <typename Type = int,
        template <typename Ti> class Container = C2> // <-- Here is the problem!
  void m() {}

};

The gnu compiler, version 4.8.1 fails with the following message:

test-temp.C:16:47: error: invalid use of type ‘C2<T>’ as a default value for a template template-parameter
      template <typename Ti> class Container = C2> 

It refers to default template parameter C2 for the the method C2::m.

Apparently (it is my opinion), the compiler is seeing C2<T> as default parameter instead of C2 (without <T>). So, when it finds the instruction it fails because type C2<T> does not match with Container.

However, clang++, just for exactly the same code, compiles fine!

My questions:

  1. Which compiler has the truth?
  2. Is there some alternative for expressing the same sense with the current version of gnu compiler?

Thanks in advance

Leandro

Was it helpful?

Solution

I think Clang is correct, and g++ is in error, quote from the draft Standard (bold emphasis is mine)

14.6.1 Locally declared names [temp.local]

1 Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injectedclass-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-typespecifier of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in <>.

You can use the :: scope resolution operator to beat g++ into submission

template <typename T> 
struct C2
{
  template <typename Type = int,
        template <typename Ti> class Container = ::C2> 
                                              // ^^ <-- here is the solution!
  void m() {}

};

Live Example.

OTHER TIPS

So does the 14.6.1 reference in TemplateRex's answer mean that G++ is correct (and Clang and VC++ are wrong) to accept this, since it uses X as the template argument to a template template parameter?

template< template< typename > class T >
class factory { };

template< typename T >
class X
{
      friend class factory< X >;  // ***
};

int main()
{
}

In this example G++ treats X as the name of the class template, whereas Clang and VC++ treat it as the injected class name.

Edit: Clang 5.0.0 now accepts the code, the same as G++ and EDG.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top