This code works:
#include <iostream>
constexpr static auto less = std::less{};
#include <string>
std::string a = "1";
std::string b = "1";
int main(){
std::cout << ( less( 6, 3 ) ? "Y" : "N" ) << '\n';
std::cout << ( less( a, b ) ? "Y" : "N" ) << '\n';
}
According en.cppreference.com, std::less is implemented like this:
template<class T>
struct Less{
constexpr bool operator()(const T &lhs, const T &rhs) const{
return lhs < rhs;
}
};
but if this is true, how std::less{};
works? It will require to pass the type - std::less<int>{};
Alternatively, if implementation is like this:
struct Less{
template<class T>
constexpr bool operator()(const T &lhs, const T &rhs) const{
return lhs < rhs;
}
};
everything will works.
But if this is like it is, why use class
and not lambda
?
Strangely enough, but this code also works:
#include <iostream>
constexpr static auto less = std::less<int>{};
#include <string>
std::string a = "1";
std::string b = "1";
int main(){
// obviously for strings it no longer works.
// std::cout << ( less( 6, 3 ) ? "Y" : "N" ) << '\n';
std::cout << ( less( a, b ) ? "Y" : "N" ) << '\n';
}
So what is really going on here?
CodePudding user response:
Since C 14 std::less
is declared as
template< class T = void >
struct less;
and it has a specialization for void
that has an operator()
with the form of
template< class T, class U>
constexpr auto operator()( T&& lhs, U&& rhs ) const
-> decltype(std::forward<T>(lhs) < std::forward<U>(rhs));
This operator()
deduces the types of the parameters for you and returns lhs < rhs
. This is what allows your first code block to compile.
In your second example you switch less
to be
constexpr static auto less = std::less<int>{};
and this forces you to have comparator that only works for int
s.
CodePudding user response:
Code for illustrating my comment to NathanOliver:
template<class T = void>
struct Less{
constexpr bool operator()(const T &lhs, const T &rhs) const{
return lhs < rhs;
}
};
template<>
struct Less<void>{
template<class A, class B>
constexpr bool operator()(const A &lhs, const B &rhs) const{
return lhs < rhs;
}
};