In my code I would like to have one operation happen before another if one object is less than another. However, if the type isn't comparable it doesn't matter the order. To achieve this, I've tried to use SFINAE:
template<typename T, typename = decltype(std::declval<std::less<T>>()(std::declval<T>(), std::declval<T>()))>
bool ComparableAndLessThan(const T& lhs, const T& rhs) {
return std::less<T>()(lhs, rhs);
}
bool ComparableAndLessThan(...) {
return false;
}
struct foo {};
int main()
{
foo a,b;
if (ComparableAndLessThan(a, b)) {
std::cout << "a first" << std::endl;
} else {
std::cout << "b first" << std::endl;
}
}
However this did not work. If I create an object without giving it a operator< or a std::less specialization, I get this error.
error C2678: binary '<': no operator found which takes a left-hand operand of type 'const foo' (or there is no acceptable conversion)
note: could be 'bool std::operator <(const std::error_condition &,const std::error_condition &) noexcept'
note: or 'bool std::operator <(const std::error_code &,const std::error_code &) noexcept'
note: while trying to match the argument list '(const foo, const foo)'
note: while compiling class template member function 'bool std::less<T>::operator ()(const _Ty &,const _Ty &) const'
with
[
T=foo,
_Ty=foo
]
I'm assuming because the declaration exists, SFINAE doesn't see this as an error, even though the implementation causes an error. Is there any way to check if std::less can be used on a templated type?