lo prendo si intende un tratto che, per due tipi L
e R
e oggetti lhs
e rhs
di quei tipi, rispettivamente, produrrà true
se l'lhs == rhs
compilerà e false
altrimenti. Apprezziamo che in teoria lhs == rhs
potrebbe compilare anche se rhs == lhs
o lhs != rhs
, no.
In tal caso si potrebbe implementare il tratto come:
#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{};
Ciò si applica un modello popolare SFINAE per la definizione dei tratti che si spiega nella risposta alla this question
Alcune illustrazioni:
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,"");
Se si desidera che il carattere richieda che l'uguaglianza sia simmetrica e quella disuguaglianza esiste anche ed è simmetrico, puoi vedere come elaborarlo tu stesso.
Thx per la risposta, ma non funziona. Anche il tuo static_assert ha esito negativo durante il tentativo di compilare questo codice con gcc. Il problema sembra essere "std :: declval() == std :: declval ()" che non viene valutato. È interessante notare che clang-3.8 genera un'eccezione compilata come mi aspetterei. –
Gene
@Gene Odd, ha compilato per me con [gcc 5.2 live] (https://goo.gl/0Le5lw) e [clang 3.6 live] (https://goo.gl/uLkdnm). Forse potresti pubblicare la tua compilazione fallita? –
Interessante ... Ho usato gcc 4.9.2 che si lamenta anche di static_assert. Anche il mio esempio locale è stato un po 'più complicato. Ho aggiunto una definizione di coppia alla fine, il che rende il clang 3.6 live anche fallire inaspettatamente: https://goo.gl/OKsuIU – Gene