Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Looking for "is_comparable" typetrait

I'm looking for an "is_comparable" typetrait but can't find any.

It's very easy to build one that checks if an operator== for a class was implemented, but this excludes global defined operators.

Is it impossible to implement a is_comparable typetait?

like image 532
Gene Avatar asked Oct 17 '15 14:10

Gene


1 Answers

I take it you mean a trait that, for two types L and R and objects lhs and rhs of those types respectively, will yield true if the lhs == rhs will compile and false otherwise. You appreciate that in theory lhs == rhs might compile even though rhs == lhs, or lhs != rhs, does not.

In that case you might implement the trait like:

#include <type_traits>

template<class ...> using void_t = void;

template<typename L, typename R, class = void>
struct is_comparable : std::false_type {};

template<typename L, typename R>
using comparability = decltype(std::declval<L>() == std::declval<R>());

template<typename L, typename R>
struct is_comparable<L,R,void_t<comparability<L,R>>> : std::true_type{};

This applies a popular SFINAE pattern for defining traits that is explained in the answer to this question

Some illustrations:

struct noncomparable{};

struct comparable_right
{
    bool operator==(comparable_right const & other) const {
        return true;
    }
};

struct any_comparable_right
{
    template<typename T>
    bool operator==(T && other) const {
        return false;
    }
};

bool operator==(noncomparable const & lhs, int i) {
    return true;
}

#include <string>

static_assert(is_comparable<comparable_right,comparable_right>::value,"");
static_assert(!is_comparable<noncomparable,noncomparable>::value,"");
static_assert(!is_comparable<noncomparable,any_comparable_right>::value,"");
static_assert(is_comparable<any_comparable_right,noncomparable>::value,"");
static_assert(is_comparable<noncomparable,int>::value,"");
static_assert(!is_comparable<int,noncomparable>::value,"");
static_assert(is_comparable<char *,std::string>::value,"");
static_assert(!is_comparable<char const *,char>::value,"");
static_assert(is_comparable<double,char>::value,"");

If you want the trait to require that equality is symmetric and that inequality also exists and is symmetric you can see how to elaborate it yourself.

like image 55
Mike Kinghan Avatar answered Dec 02 '22 05:12

Mike Kinghan