Referring to C ++ Templates

Given the class of patterns, when should we explicitly refer to the pattern, and when the compiler "understands that we meant it"

taking into account the following cases:

1) function return value and arguments

2) internal declaration function

3) namespace SomeClass<T>:: vs. SomeClass::

Is there any rule? Sometimes I saw:

 SomeClass 

and sometimes: SomeClass<T>

and i didn't get the rule

+5
source share
2 answers

class template parameters can only be omitted inside the implementation of this class, where they implicitly add the appropriate template qualifier to the class, and when accessing an independent base class (they are not dependent, as in "do not reuse any template arguments"). For instance:

 template<typename T, typename U> class C { /* here C is the same as C<T, U> */ }; template<typename T> class C<void, T> { /* here C is the same as C<void, T> */ }; template<> class C<void, void> { /* here C is the same as C<void, void> */ }; template<typename> struct Base { }; struct DerivedA : Base<void> { /* here Base is the same as Base<void> */ }; template<typename T> struct DerivedB : Base<T> { /* here Base is invalid, since Base<T> depends on a template argument */ }; 

Function templates can have their template parameters omitted if they can be inferred from their arguments:

 template<typename T> void f(T f); f(3); // equivalent to f<int>(3) if no other overload exists 

In addition, there are default template arguments, which leads to something really funky :

 template<typename T = void> class D { // Here D is D<T>, but D<> is D<void> instead! }; 
+3
source

The standard describes all scripts in [temp.local]:

  • Like regular (non-template) classes, class templates have a name with the class introduced (section 9). The name of the entered class can be used as a template name or type name. When used with template-argument-list, as a template argument for a template template, or as a trailing identifier in a specified type specifier of a friend of a class template declaration, it refers to the class template itself. Otherwise, this is equivalent to the name of the template, followed by the template parameters of the template class enclosed in <> .

  • For a class template specialization or partial specialization, when the name of the entered class is used as the type name, this is equivalent to the template name, followed by the classtemplate specialization template arguments or the partial specialization enclosed in <> .

[Example:

 template<template<class> class T> class A { }; template<class T> class Y; template<> class Y<int> { Y* p; // meaning Y<int> Y<char>* q; // meaning Y<char> A<Y>* a; // meaning A<::Y> class B { template<class> friend class Y; // meaning ::Y }; }; 

-end example]

This only works inside the class template (i.e. the namespace of the entered class) and only if the name is accessible from the corresponding scope:

When a normal template name (that is, the name is from a spanning scope, not the name of an entered class), it always refers to the class template itself, and not to the template specialization. [Example:

 template<class T> class X { X* p; // meaning X<T> X<T>* p2; X<int>* p3; ::X* p4; // error: missing template argument list // ::X does not refer to the injected-class-name }; 

-end example]

And for base classes, where the base is independent:

A search that finds a name with the class entered (10.2) can lead to ambiguity in some cases (for example, if it occurs in more than one base class). If all the entered class names that are found refer to the specializations of the same class template, and if the name is used as the template name, the link refers to the class template itself, and not its specialization, not ambiguous. [Example:

 template <class T> struct Base { }; template <class T> struct Derived: Base<int>, Base<char> { typename Derived::Base b; // error: ambiguous typename Derived::Base<double> d; // OK }; 

-end example]

We can modify the example a bit to show what would be right:

 template <class T> struct Base { }; template <class T> struct Derived: Base<char> { typename Derived::Base b; // Ok: b refers to Base<char> }; 
0
source

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


All Articles