Как повторно использовать операторные перегрузки для разных типов? - PullRequest
0 голосов
/ 29 декабря 2018

У меня есть несколько enums, определенных следующим образом:

enum class Suit {
    spades = 1, hearts, diamonds, clubs,
    first = spades, last = clubs
};

enum class Rank {
    six = 6, seven, eight, nine, ten, jack, queen, king, ace,
    first = six, last = ace
};

Для каждого из этих enums я перегружен некоторыми операторами:

Suit operator++(Suit& r) { return r = (Suit)(static_cast<std::underlying_type_t<Suit>>(r) + 1); }
Rank operator++(Rank& r) { return r = (Rank)(static_cast<std::underlying_type_t<Rank>>(r) + 1); }
// more overloads ...

Обратите внимание, что реализацияПерегрузки операторов одинаковы для обоих типов. Как мне избежать этого дублирования кода?

Я мог бы использовать шаблоны ...

template<class T>
T operator++(T& r) { return r = (T)(static_cast<std::underlying_type_t<T>>(r) + 1); }

, но эти перегрузки должны применяться только к моим пользовательским типам.

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Вот как вы можете ограничить ваши шаблоны в масштабируемой форме.

#include <type_traits>

template <class> 
constexpr bool is_my_enum = false;       // most types are not my enums

enum class Suit {
    spades = 1, hearts, diamonds, clubs,
    first = spades, last = clubs
};
template<> 
constexpr bool is_my_enum<Suit> = true;  // this is my enum

enum class Rank {
    six = 6, seven, eight, nine, ten, jack, queen, king, ace,
    first = six, last = ace
};
template<> 
constexpr bool is_my_enum<Rank> = true;  // this one is mine too

enum class Moo { moo = 0 };              // but this one isn't



// define functions for my enums only
template<class T>
using for_my_enums = std::enable_if_t<is_my_enum<T>, T>;

template<class T> 
for_my_enums<T>                        
operator++(T& r) {return r = (T)(static_cast<std::underlying_type_t<T>>(r) + 1);}

template<class T> 
for_my_enums<T>                        
operator++(T& r, int) { 
    auto k = r; 
    r = (T)(static_cast<std::underlying_type_t<T>>(r) + 1); 
    return k;
}

// ... more functions ...


int main()
{
   Suit a = Suit::spades;
   ++a;                   // ok
   Moo b = Moo::moo;
   ++b;                   // compilation error, it's not my enum
}
0 голосов
/ 29 декабря 2018

Вы можете использовать свою шаблонную версию, ограничивая ее перечислениями, которые вы хотите

template <class E, std::enable_if_t<
    std::is_same_v<E, Suit> ||
    std::is_same_v<E, Rank>, bool> = true>
E& operator++(E& r, int) {
    return r = (E)(static_cast<std::underlying_type_t<E>>(r) + 1);
}
...