Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

total template specialization

Tags:

c++

I'm reading the book of Meyers about effective c++ programming, in item 25 I found total template specialization, but I can't understand it, what does that it mean? he also gives example:

namespace std {

    template<>
    void swap<Widget>(Widget& a, Widget& b)
      {
          swap(a.pimpl, b.pimpl);
      }

    }

what does this statement mean : template<>(why without typename?)

thanks in advance

like image 259
rookie Avatar asked Oct 13 '10 22:10

rookie


People also ask

What is a 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.

How many types of templates are there?

There are three kinds of templates: function templates, class templates and, since C++14, variable templates. Since C++11, templates may be either variadic or non-variadic; in earlier versions of C++ they are always non-variadic.

What is full specialization?

Explicit (full) specializationAllows customizing the template code for a given set of template arguments.

How many types of specialization are there in C++?

How many types of specialization are there in c++? Explanation: There are two types of specialization. They are full specialization and partial specialization.


1 Answers

Typically you use templates because you have a piece of code that is generic enough that it can be applied to different types. However, for some types you may want to do something different (e.g. because there's a more efficient way of doing it). This is when template specialization comes to the rescue (you can think of them as "special case" templates):

For example:

class Foo {};
class Bar {};

// Primary template - the most generic.
template<typename T, typename U>
class MyClass
{
public:
    void DoSomething()
    {
        /* Performs the same generic operation for all T and U... */
    }
};

// Total specialization of the primary template
template<>
class MyClass<Foo, Bar>
{
public:
    void DoSomething()
    {
        /* ...Except when T is Foo and U is Bar.
              We may possibly do something different
              to allow for higher efficiency. */
    }
};

int main()
{
    MyClass<int, char> a; // Uses the generic version of MyClass
    MyClass<Foo, Bar> b;  // Uses the (total) template specialization
}

Note that I'm using classes here, but the concept is the same. You can see that a similar syntax applies for function templates.

For classes, though, there is such a thing as partial template specialization, when not all the parameters are completely specified in the template specialization. It might look like this:

// Partial specialization #1
template<typename U>
class MyClass<Foo, U>
{
public:
    void DoSomething()
    {
        /* ...Do something special when T is Foo.
              This code doesn't care what type U is. */
    }
};

template<typename T> class Baz {};

// Partial specialization #2
template<typename Z>
class MyClass<Foo, Baz<Z> >
{
public:
    void DoSomething()
    {
        /* ...Do something special when T is Foo, and U is Baz.
              This code doesn't care what Baz gets for its
              template parameter. */
    }
};

int main()
{
    MyClass<int, char> a;      // Uses the generic version of MyClass
    MyClass<Foo, char> b;      // Uses partial template specialization #1
    MyClass<Foo, Baz<int> > c; // Uses partial template specialization #2
    MyClass<Foo, Bar> d;       // Uses the total template specialization
}

Note that there's no ambiguity when dealing with these specializations because the compiler picks the one that is the best fit for the template parameters. By allowing for these "special case" templates, we can create truly generic libraries.

Also note that this partial specialization business only works for classes, not functions! (You can't partially specialize function templates). That's why your code snippet is written the way it is - you can only totally specialize function templates - anything else is function overloading in the std namespace (which the C++ standard disallows). I took the time to mention this because lots of people seem to get this wrong.

namespace std
{
    /* Do **not** do this in the std namespace!!!
       You're not actually partially specializing the function,
       you're overloading the function in the std namespace
       which is prohibited by the C++ standard. */
    template<typename T>        
    void swap<Widget<T> >(Widget<T>& a, Widget<T>& b) {}
}
like image 82
In silico Avatar answered Sep 19 '22 22:09

In silico