Reputation: 17999
I have several enums
defined as follows:
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
};
For each of these enums
I have overloaded some operators:
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 ...
Note that the implementation of the operator overloads is the same for both types. How can I avoid this code duplication?
I could use templates...
template<class T>
T operator++(T& r) { return r = (T)(static_cast<std::underlying_type_t<T>>(r) + 1); }
but these overloads should apply to my custom types only.
Upvotes: 0
Views: 100
Reputation: 119867
Here's how you can restrict your templates in a scalable manner.
#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
}
Upvotes: 2
Reputation: 11250
You could use your templated version restricting it on the enums you want
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);
}
Upvotes: 1