Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class template specialization in class scope?

Why is the specialization S in A legal and S in B not?

( if B is not commented out ) GCC 4.8.1: error: explicit specialization in non-namespace scope ‘class B’

#include <type_traits>
#include <iostream>

class Y {};
class X {};

struct A {
  template<class T, class = void>
  class S;

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct S < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };
};

/*
class B
{
    template<class T>
    class S;

    template<>
    class S < Y > {};

    template<>
    class S < X > {};
};
*/


int main()
{
    A::S< X > asd;
    std::cout << asd.i << std::endl;
}

on coliru: B commented out

on coliru: with B (error)

like image 222
Monotomy Avatar asked Sep 19 '13 20:09

Monotomy


People also ask

What is meant by template specialization?

The act of creating a new definition of a function, class, or member of a class from a template declaration and one or more template arguments is called template instantiation. The definition created from a template instantiation is called a specialization.

Are template specializations inline?

An explicit specialization of a function template is inline only if it is declared with the inline specifier (or defined as deleted), it doesn't matter if the primary template is inline.

What is the difference between a template and a class?

An individual class defines how a group of objects can be constructed, while a class template defines how a group of classes can be generated. Note the distinction between the terms class template and template class: Class template.

What is the syntax for explicit class specialization?

What is the syntax to use explicit class specialization? Explanation: The class specialization is creation of explicit specialization of a generic class. We have to use template<> constructor for this to work. It works in the same way as with explicit function specialization.


1 Answers

The comments by @jrok pretty much explains your compiler error. Nested classes in general, and nested class templates in particular, are a dusty corner of the language that you can easily avoid (taking to heart Sutter's advice "Write what you know and know what you write").

Simply make a namespace detail to define your class templates SA and SB and their specializations and then define a nested template type alias S inside both A and B

namespace detail {

  template<class T, class = void>
  class SA;

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< Y, T >::value >::type > 
  {
    int i = 0;
  };

  template<class T>
  struct SA < T, typename std::enable_if< std::is_same< X, T >::value >::type > 
  {
    int i = 1;
  };

  template<class T>
  class SB;

  template<>
  class SB < Y > {};

  template<>
  class SB < X > {};
}

struct A
{
    template<class T>
    using S = detail::SA<T>;
};

struct B
{
    template<class T>
    using S = detail::SB<T>;
};

Granted, for this case it might seem overkill, but if you ever want to make A and B class templates themselves, and specialize A and B, then you can only specialize the nested class templates if you also specialize the enclosing class. In short: just avoid these issues altogether by an extra level of compile-time indirection.

like image 188
TemplateRex Avatar answered Oct 29 '22 10:10

TemplateRex