Reputation: 3373
Considering Template Class when do we have to refer explicitly to template, and when the compiler "understands that we meant it"
considering the following occurences:
1) function return value & arguements
2) variable declaration inside function
3) namespace SomeClass<T>::
vs. SomeClass::
Is there any rule? I saw sometimes the use is of:
SomeClass
and sometimes: SomeClass<T>
and I didn't get the rule
Upvotes: 5
Views: 138
Reputation: 60999
The standard describes all scenarios in [temp.local]:
Like normal (non-template) classes, class templates have an injected-class-name (Clause 9). The injected-class-name can be used as a template-name or a type-name. When it is used with a template-argument-list, as a template-argument for a template template-parameter, or as the final identifier in the elaborated-type-specifier of a friend class template declaration, it refers to the class template itself. Otherwise, it is equivalent to the template-name followed by the template-parameters of the class template enclosed in
<>
.Within the scope of a class template specialization or partial specialization, when the injected-class-name is used as a type-name, it is equivalent to the template-name followed by the template-arguments of the classtemplate specialization or 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 scope of the injected-class-name), and only if the name is accessed from a corresponding scope:
When the normal name of the template (i.e., the name from the enclosing scope, not the injected-class-name) is used, it always refers to the class template itself and not a specialization of the template. [ 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 not dependent:
A lookup that finds an injected-class-name (10.2) can result in an ambiguity in certain cases (for example, if it is found in more than one base class). If all of the injected-class-names that are found refer to specializations of the same class template, and if the name is used as a template-name, the reference refers to the class template itself and not a specialization thereof, and is 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 slightly to show what would be valid:
template <class T> struct Base { };
template <class T> struct Derived: Base<char> {
typename Derived::Base b; // Ok: b refers to Base<char>
};
Upvotes: 0
Reputation: 11126
Class template parameters may only be omitted inside the implementation of that class, where they implicitly add the appropriate template specifiers to the class and when referring to a non-dependent base class (non-dependent as in "does not reuse any template arguments"). For example:
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 may have their template parameters omitted, if they can be deduced from their arguments:
template<typename T>
void f(T f);
f(3); // equivalent to f<int>(3) if no other overload exists
Additionally, 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!
};
Upvotes: 3