I try to understand the docs for std::less, where the following example is given for the usage with a template.
#include <functional>
#include <iostream>
template <typename A, typename B, typename C = std::less<>>
bool fun(A a, B b, C cmp = C{})
{
return cmp(a, b);
}
int main()
{
std::cout
<< std::boolalpha
<< fun(1, 2) << ' ' // true
<< fun(1.0, 1) << ' ' // false
<< fun(1, 2.0) << ' ' // true
<< std::less<int>{}(5, 5.6) << ' ' // false: 5 < 5 (warn: implicit conversion)
<< std::less<double>{}(5, 5.6) << ' ' // true: 5.0 < 5.6
<< std::less<int>{}(5.6, 5.7) << ' ' // false: 5 < 5 (warn: implicit conversion)
<< std::less{}(5, 5.6) << ' ' // true: less<void>: 5.0 < 5.6
<< '\n';
}
Output:
true false true false true false true
My question is:
How is a std:: function used as a template argument?
And in this concrete case, why are there curly brackets {} behind the C cmp = C or in the call std::less<double>{}(5, 5.6)?
>Solution :
This demo-code suffers from so-called ‘uniform initialisation’ (broken by design, be careful with its use especially in template code!), classic way to write the same code before uniform initialisation is:
std::less<int>()(5, 5.6); // others analogously
std::less is a callable class, a so-called ‘functor’, which means it provides an operator() by which objects of the class can be called just like a function (to be precise: the operator is a member function that gets called, just the syntax for getting called actually is the same).
The code presented now first constructs such an object (calls the constructor; first pair of parentheses) while afterwards the so constructed object is called (the operator() with two arguments, second pair of parentheses).
Equivalent code could be:
std::less<int> li; // note that the parentheses need to be left out;
// braces for uniform initialisation could remain
li(5, 5.6);
Note, though, that the life-time of the object li is now longer is longer (until leaving the current scope) than the one of the temporary (only current expression). In given case, there are no visible side effects, though, notably as std::less doesn’t have any in its destructor.