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>.