What is this template design?

This is from the xutility header of the C ++ Standard Library that ships with VS2012.

template<class _Elem1, class _Elem2> struct _Ptr_cat_helper { // determines pointer category, nonscalar by default typedef _Nonscalar_ptr_iterator_tag type; }; template<class _Elem> struct _Ptr_cat_helper<_Elem, _Elem> { // determines pointer category, common type typedef typename _If<is_scalar<_Elem>::value, _Scalar_ptr_iterator_tag, _Nonscalar_ptr_iterator_tag>::type type; }; 

In particular, what is the nature of the second _Ptr_cat_helper declaration? The angle brackets after the _Ptr_cat_helper declarator make it look like a specialization. But instead of specifying full or partial types by which the specialization of the template instead, just repeat the template argument several times.

I don’t think I have seen this before. What is it?

UPDATE

We are all clear that specialization applies to an instance of a template where both template arguments are of the same type, but I don’t understand whether this is a full or partial specialization or why.

I thought that specialization was a complete specialization, when all template arguments are either explicitly supplied or provided by default arguments, and are used in the same way as provided for creating a template instance, and, on the contrary, specialization was partial either if not all template parameters were necessary because of the specialization that provides one or more (but not all) of them, and / or if the template arguments were used in a form that was modified by the specialization template. For instance.

Specialization, which is partial, since specialization provides at least one, but not all, of the template arguments.

 template<typename T, typename U> class G { public: T Foo(T a, U b){ return a + b; }}; template<typename T> class G<T, bool> { public: T Foo(T a, bool b){ return b ? ++a : a; }}; 

Specialization, which is partial, because specialization leads to the fact that the argument of the provided template is used only partially.

 template<typename T> class F { public: T Foo(T a){ return ++a; }}; template<typename T> class F<T*> { public: T Foo(T* a){ return ++*a; }}; 

In this second example, if the template was created using A <char *>, then T in the template will actually be of type char, that is, the template argument, as indicated, is used only partially due to the use of the specialization template.

If this is correct, this will not make the template in the original question a full specialization, not a partial specialization, and if it is not, then where is my misunderstanding?

+4
source share
2 answers

This is a private specialization of the class template for the case when the same type is passed for both parameters.

It might be easier to read:

 template<typename T, typename U> struct is_same : std::false_type {}; template<typename T> struct is_same<T,T> : std::true_type {}; 

EDIT:

If you have doubts about whether a specialization is an explicit (full) specialization or a partial specialization, you can refer to a standard that is pretty clear on this point:

n3337, 14.7.3./1

Explicit specialization in any of the following:

[...]

may be declared by the declaration introduced by template<> ; i.e:

explicit specialization:
template < > Announcement

and n3337, 14.5.5 / 1

A template declaration of a main class is a class in which the class template name is an identifier. A template declaration in which the class template name is a simple identifier template is a partial specialization of the class template named in the simple-template-id identifier. [...]

If a simple identifier pattern is defined in the grammar:

simple ID template:

template_name <template-argument-list opt>

name template

identifier

So, wherever template<> , this is full specialization, everything else is partial specialization.

You can also think of it this way: A complete specialized specialization specializes in only one possible instance of the primary template. Everything else is partial specialization. The example in your question is a partial specialization, because since it restricts arguments of the same type, it still allows an infinite number of different arguments with which the template can be created.

Such specialization, for example

 template<> vector<bool> { /* ... */ }; 

- full specialization, because it works when the type is bool and only bool .

Hope this helps.


And just a note that I think is worth mentioning. I think you already know that function templates cannot be partially specialized. Although it is

 template<typename T> void foo(T); template<typename T> void foo(T*); 

may look like a partial specialization of foo for pointers at a glance, it's not - it's an overload.

+11
source

You indicate that when performing template specialization, “full or incomplete type” is indicated, which assumes that you know about a language function such as partial specialization of class templates.

Partial specialization has quite extensive functionality. This is not limited to just specifying specific arguments for some template parameters. It also allows you to define a dedicated version of the template for certain groups of argument types based on their cv-qualifications or levels of indirection, as in the following example

 template <typename A, typename B> struct S {}; // Main template template <typename A, typename B> struct S<A *, B *> {}; // Specialization for two pointer types template <typename A, typename B> struct S<const A, volatile B> {}; // Specialization for const-qualified type `A` and volatile-qualified type `B` 

And it also covers specializations based on whether some template arguments are the same or different

 template <typename A> struct S<A, A> {}; // Specialization for two identical arguments template <typename A> struct S<A, A *> {}; // Specialization for when the second type is a pointer to the first one 

As another, rather curious example, a partial specialization of a template with several arguments can be used to completely override the main template.

 template <typename A, typename B> struct S<B, A> {}; // Specialization for all arguments 

Now, returning to your sample code, partial specialization for two identical arguments is exactly what is used in the code you sent.

+5
source

Source: https://habr.com/ru/post/1490790/


All Articles