2015-10-17 17 views
6

Szukam "is_comparable" typetrait, ale nie można znaleźć.Szukam "is_comparable" typetrait

Bardzo łatwo jest zbudować taki, który sprawdza, czy klasa operator== została zaimplementowana, ale nie obejmuje operatorów zdefiniowanych globalnie.

Czy nie można wdrożyć typizestawu is_comparable?

Odpowiedz

3

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ć.

+0

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

+0

@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ę? –

+0

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