Za chwilę przeprowadzimy (w ciągu najbliższych dwóch lat) wszystkie nasze kompilatory do kompilatorów C++ 11-ready.Czy ten wzorzec jest prawidłowy dla migracji wstecznej z C++ 03 do klasy enum C++ 11?
Nasi klienci wykorzystają nasze nagłówki i jesteśmy teraz w stanie napisać (mniej lub bardziej od zera) nagłówki naszego nowego interfejsu API.
Musimy więc wybrać między utrzymaniem C++ 03 (z ich wszystkimi brodawkami) lub użyciem klasy zawijania do symulacji notacji C++ 11, ponieważ chcemy, na koniec, przenieść te enumy do C + +11.
Czy proponowany pomysł "LikeEnum" jest poniżej realnego rozwiązania, czy też kryją się za nim niespodziewane niespodzianki?
template<typename def, typename inner = typename def::type>
class like_enum : public def
{
typedef inner type;
inner val;
public:
like_enum() {}
like_enum(type v) : val(v) {}
operator type() const { return val; }
friend bool operator == (const like_enum & lhs, const like_enum & rhs) { return lhs.val == rhs.val; }
friend bool operator != (const like_enum & lhs, const like_enum & rhs) { return lhs.val != rhs.val; }
friend bool operator < (const like_enum & lhs, const like_enum & rhs) { return lhs.val < rhs.val; }
friend bool operator <= (const like_enum & lhs, const like_enum & rhs) { return lhs.val <= rhs.val; }
friend bool operator > (const like_enum & lhs, const like_enum & rhs) { return lhs.val > rhs.val; }
friend bool operator >= (const like_enum & lhs, const like_enum & rhs) { return lhs.val >= rhs.val; }
};
co pozwoliłoby nam uaktualnić nasze teksty stałe bez konieczności niepożądanych zmian w kodzie użytkownika:
// our code (C++03) | our code C++11
// --------------------------------------+---------------------------
|
struct KlingonType | enum class Klingon
{ | {
enum type | Qapla,
{ | Ghobe,
Qapla, | Highos
Ghobe, | } ;
Highos |
} ; |
} ; |
|
typedef like_enum<KlingonType> Klingon ; |
|
// --------------------------------------+---------------------------
// client code (both C++03 and C++11)
void foo(Klingon e)
{
switch(e)
{
case Klingon::Qapla : /* etc. */ ; break ;
default : /* etc. */ ; break ;
}
}
Uwaga: LikeEnum była inspirowana przez Type Safe Enum idiom
nocie 2 : Kompatybilność źródeł nie obejmuje błędu kompilacji z powodu niejawnej konwersji na int: są one uznawane za niepożądane, a klient zostanie powiadomiony w adv do bezpośredniej konwersji na liczbę całkowitą.
Wykonaj dwa z 'wewnętrznego' funkcji 'szablonu', którą SFINAE zapewnia, że żądany typ to' wewnętrzny', aby uniknąć jedno-pośrednich konwersji jednego użytkownika? Lub użyć typu pośredniego? Kod idola i problem w zasadzie ... (lub czy problem ten nie dotyczy 'enum's?) – Yakk