biorę go na myśli cechę, że dla dwóch typów L
i R
i obiektów lhs
i rhs
z tych typów odpowiednio, przyniesie true
jeśli lhs == rhs
skompiluje i false
inaczej. Docenisz to, że w teorii lhs == rhs
może się kompilować, mimo że rhs == lhs
, lub lhs != rhs
, nie.
W takim przypadku można realizować cechy jak:
#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{};
Dotyczy to popularny wzór SFINAE definiowania cech, które są wyjaśnione w odpowiedzi na this question
Niektóre ilustracje:
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,"");
Jeśli chcesz, aby cecha wymagała równości jest symetryczna, a nierówność również istnieje i jest symetryczny, możesz sam go opracować.
Thx za odpowiedź, ale nie działa. Nawet Twój static_assert nie powiedzie się, próbując skompilować ten kod za pomocą gcc. Problemem wydaje się być "std :: declval() == std :: declval ()", który nie zostanie oceniony. Co ciekawe clang-3.8 generuje wyjątek kompilacji, jak można się było spodziewać. –
Gene
@Gene Odd, skompilowano dla mnie z [gcc 5.2 live] (https://goo.gl/0Le5lw) i [clang 3.6 live] (https://goo.gl/uLkdnm). Może mógłbyś opublikować swoją wadliwą kompilację? –
Interesujące ... Użyłem gcc 4.9.2, który również narzeka na static_assert. Mój lokalny przykład również był nieco bardziej skomplikowany. Dodałem definicję pary na końcu, co sprawia, że clang 3.6 również nieoczekiwanie kończy się niepowodzeniem: https://goo.gl/OKsuIU – Gene