Difference between instantiation and specialization in c++ templates

What is the difference between specialization and instantiation in context of C++ templates. From what I have read so far the following is what I have understood about specialization and instantiation.

template <typename T>
struct Struct
{

     T x;
};

template<>
struct Struct <int> //specialization
{

    //code
};

int main()
{
   Struct <int> s; //specialized version comes into play
   Struct <float> r; // Struct <float> is instantiated by the compiler as shown below

}

Instantiation of Struct <float> by the compiler

template <typename T=float>
struct Struct
{
    float x;
}

Is my understanding of template instantiation and specialization correct?


(Implicit) Instantiation

This is what you refer to as instantiation (as mentioned in the Question)

Explicit Instantiation

This is when you tell the compiler to instantiate the template with given types, like this:

template Struct<char>; // used to control the PLACE where the template is inst-ed

(Explicit) Specialization

This is what you refer to as specialization (as mentioned in the Question)

Partial Specialization

This is when you give an alternative definition to a template for a subset of types, like this:

template<class T> class Struct<T*> {...} // partial specialization for pointers

What is the difference between specialization and instantiation in context of C++ templates?

Normally (no specializations present) the compiler will create instantiations of a template when they are used, by substituting actual template parameters (int in your example) for the formal template parameters (T) and then compile the resulting code.

If a specialization is present, then for the (set of) special template parameter(s) specified by that specialization, that specialization's implementation is to be used instead of what the compiler would create.


A template specialization actually changes the behaviour of the template for a specific type. eg convert to a string:

template<typename T> std::string convertToString( const T& t )
{
   std::ostringstream oss;
   oss << t;
   return oss.str();
}

Let's specialise that though when our type is already a std::string as it is pointless going through ostringstream

template<> std::string convertToString( const std::string & t )
{
   return t;
}

You can specialise for classes too.

Now instantiation: this is done to allow you to move the compilation for certain types into one compilation unit. This can save you both compilation time and sometimes code-bloat too. Let's say we make the above into a class called StringConvert rather than a function.

template<typename T>
class StringConvert
{
 public:
  // 4 static functions to convert from T to string, string to T,
   // T to wstring and wstring to T using streams
 };

We will convert a lot of integers to strings so we can instantiate it: Put this inside one header

 extern template class StringConvert<int>;

Put this inside one compilation unit:

 template class StringConvert<int>;

Note that the above can also be done (without the extern in the header) with functions that are actually not implemented inline. One of your compilation units will implement them. However then your template is limited only to instantiated types. Sometimes done when the template has a virtual destructor.


Overview

  • Specialization: The class, function or class member you get when substituting template arguments into the template parameters of a class template or function template.

  • Instantiation: The act of creating a specialization out of a template or class template member. The specialization can be created out of a partial specialization, class template member or out of a primary class or function template.

An explicit specialization is one that defines the class, function or member explicitly, without an instantiation.


In c++ 11.

instantiation:

Instantiate the template with given template arguments

template <typename T>
struct test{ T m; };

template test<int>;//explicit instantiation

which result in a definition of a struct with a identifier test<int>

test<int> a;//implicit instantiation

if template <typename T> struct test has been instantiated with argument T = int before(explicit or implicit), then it's just a struct instantiation. Otherwise it will instantiate template <typename T> struct test with argument T = int first implicitly and then instantiate an instance of struct test<int>

specialization:

a specialization is still a template, you still need instantiation to get the real code.

template <typename T>
struct test{ T m; };
template <> struct test<int>{ int newM; } //specialization

The most useful of template specialization is probably that you can create different templates for different template arguments which means you can have different definitions of class or function for different template arguments.

template<> struct test<char>{ int cm; }//specialization for char
test<char> a;
a.cm = 1;

template<> struct test<long> { int lm; }//specialization for long
test<long> a;
a.lm = 1;

In addition to these full template specializations above, there(only class template) exits partial template specialization also.

template<typename T>
struct test {};
template <typename T> struct test<const T>{};//partial specialization for const T


template <typename A, typename B>
struct test {};
template <typename B> struct test<int, B>{};//partial specialization for A = int