What Is the Meaning of Template<> with Empty Angle Brackets in C++

What is the meaning of template with empty angle brackets in C++?

template<> tells the compiler that a template specialization follows, specifically a full specialization. Normally, class A would have to look something like this:

template<class T>
class A{
// general implementation
};

template<>
class A<int>{
// special implementation for ints
};

Now, whenever A<int> is used, the specialized version is used. You can also use it to specialize functions:

template<class T>
void foo(T t){
// general
}

template<>
void foo<int>(int i){
// for ints
}

// doesn't actually need the <int>
// as the specialization can be deduced from the parameter type
template<>
void foo(int i){
// also valid
}

Normally though, you shouldn't specialize functions, as simple overloads are generally considered superior:

void foo(int i){
// better
}

And now, to make it overkill, the following is a partial specialization:

template<class T1, class T2>
class B{
};

template<class T1>
class B<T1, int>{
};

Works the same way as a full specialization, just that the specialized version is used whenever the second template parameter is an int (e.g., B<bool,int>, B<YourType,int>, etc).

Empty angle brackets in template definition

template<> void f<0>() {}

is specialization of function template for argument 0, if you call f<0>() this version of function will be called.

This code is incorrect, it cause linking errors, since there is no specialization for f<1> and template version of function is not defined.

Empty angle brackets on user defined types

Not this case (default template argument, as in the Jarod42's answer) but that syntax can also declare an object of a variadic template type with empty list of template arguments.

Or both.

#include <iostream>

// default value
template <typename = void>
struct foo
{ };

// variadic list
template <int ...>
struct bar
{ };

// both
template <int = 0, typename ...>
struct foobar
{ };

int main ()
{
foo<> f;
bar<> b;
foobar<> fb;
}

The funny part it that you can't distinguish the cases from variable declarations.

Do we still need to write the empty angle brackets when using transparent std function objects?

GCC is wrong. There is already a bug report.

[dcl.type.simple]/2 says:

A type-specifier of the form typenameopt nested-name-specifieropt template-name is a placeholder for a deduced class type ([dcl.type.class.deduct]).

And [dcl.type.class.deduct]/2 says:

A placeholder for a deduced class type can also be used in the type-specifier-seq in the new-type-id or type-id of a new-expression, as the simple-type-specifier in an explicit type conversion (functional notation) ([expr.type.conv]), or as the type-specifier in the parameter-declaration of a template-parameter. A placeholder for a deduced class type shall not appear in any other context.

Such use is allowed.


[temp.arg]/4 describes the syntax error that a template-id is required but there is no <>. However here std::greater is not resolved as a template-id so that paragraph does not apply.

Avoid angle brackets in default template

Since C++17, because of class template argument deduction, things have changed.

tt and tt<> are not the same thing: types and class templates were different and continue to be treated differently.

Anyway in simple scenarios like the one in your example, C++17 assumes what you mean and the <> aren't needed anymore.

Further details:

  • Template default arguments (specifically https://stackoverflow.com/a/50970942/3235496);
  • Why is <> required when specifying a template class which has defaults for all its template parameters?

What is template templatetypename T syntax for?

Answering my own question (Thanks to Story Teller and Max Vollmer for the tips), this code is invalid:

template <>
template < typename T >
class Foo<Foo2<T>>
{
...
};

While, regarding the use of the template <...> template <...> syntax, it is necessary for the definition of a templated method inside a templated class. E.g:

template < T > template < U > void Foo<T>::function() { }


Related Topics



Leave a reply



Submit