What does void mean, or how does it affect T in this case?
In general it just means that you are going to specialize a class for the type void to process a special case.
Here is a demonstrative program.
#include <iostream>
template <class T = void>
struct A
{
void operator ()( const T & t ) const
{
std::cout << "primary template\n";
std::cout << 2 * t << '\n';
}
};
template <>
struct A<>
{
template <typename U>
void operator ()( const U &u ) const
{
std::cout << "specialization for void\n";
std::cout << 10 * u << '\n';
}
};
int main()
{
A<int>()( 1 );
A<>()( 1 );
}
Its output is
primary template
2
specialization for void
10
Given your code snippet I am going to assume you are referring the function object from the standard library, that is, std::less.
In general, the declaration template<class T = void>
works exactly as for other types (such as int
, for example).
In short, when an object of that class is instantiated without specifying the type template argument, then void
will be deducted.
std::less<int> li; // std::less<T = int>;
std::less<void> lv; // std::less<T = void>;
std::less<> lv2; // std::less<T = void>; exactly as one row above.
In this particular case, std::less
provides a template specialization when T = void
.
The object std::less<void>
is a handy specialization which allows deducing the types to compare "automatically" with the operator()
. Moreover, it needed when you want to compare two different types which are not implicitly convertible.
Practical Example:
Let us assume you have two objects you can compare.
/*Let us assume you have two objects you can compare*/
struct Foo;
struct Bar;
struct Foo {
bool operator<(const Bar&) const;
};
struct Bar {
bool operator<(const Foo&) const;
};
Foo
and Bar
can be compared to each other, but they are different types.
Which template type will you specify for the functor std::less
in this case?
void WrongCode() {
std::less<Foo> l;
l(Foo{}, Bar{}); // error
}
If we use std::less<Foo>
then the functor will only accept objects of type Foo
. (Of course, the same is for std::less<Bar>
).
Therefore, the standard provides this handy specialization to cover this case.
void GoodCode() {
std::less<> l;
l(Foo{}, Bar{}); // this compile
}
GoodCode
will compile because the types of operator()
of std::less<void>
are automatically deducted (and they can even be different).
void
is a type.
There are some restrictions on how the void
type may be used, but nevertheless, void
is a valid type in the type system. Therefore, it is allowed to have void
as an argument for a template parameter, including as a default argument.
So, if you type std::less<>
then it means std::less<void>
.
The question of what std::less<void>
means is a separate one: normally, std::less<T>
compares T
values, but there are no values of type void
. Instead, std::less<void>
is a special case: you can pass two values of any (possibly different) types to it, as long as they can be compared. See the cppreference.com article on std::less<void>
.