2010-05-31 33 views
0

En réponse à la question SO précédente "Enumerate over an enum in C++", j'ai trouvé la solution réutilisable suivante qui utilise type-safe enum idiom. Je suis juste curieux de voir les commentaires de la communauté sur ma solution. Cette solution utilise un tableau statique, qui est rempli à l'aide d'objets enum sécurisés avant la première utilisation. L'itération sur les énumérations est ensuite simplement réduite à l'itération sur le tableau. Je suis conscient du fait que cette solution ne fonctionnera pas si les enquêteurs n'augmentent pas strictement.Retour d'itération sur les énumérations de type sécurisé

template<typename def, typename inner = typename def::type> 
class safe_enum : public def 
{ 
    typedef typename def::type type; 
    inner val; 

    static safe_enum array[def::end - def::begin]; 
    static bool init; 

    static void initialize() 
    { 
    if(!init) // use double checked locking in case of multi-threading. 
    { 
     unsigned int size = def::end - def::begin; 
     for(unsigned int i = 0, j = def::begin; i < size; ++i, ++j) 
     array[i] = static_cast<typename def::type>(j); 
     init = true; 
    } 
    } 

public: 

    safe_enum(type v = def::begin) : val(v) {} 
    inner underlying() const { return val; } 

    static safe_enum * begin() 
    { 
    initialize(); 
    return array; 
    } 

    static safe_enum * end() 
    { 
    initialize(); 
    return array + (def::end - def::begin); 
    } 

    bool operator == (const safe_enum & s) const { return this->val == s.val; } 
    bool operator != (const safe_enum & s) const { return this->val != s.val; } 
    bool operator < (const safe_enum & s) const { return this->val < s.val; } 
    bool operator <= (const safe_enum & s) const { return this->val <= s.val; } 
    bool operator > (const safe_enum & s) const { return this->val > s.val; } 
    bool operator >= (const safe_enum & s) const { return this->val >= s.val; } 
}; 

template <typename def, typename inner> 
safe_enum<def, inner> safe_enum<def, inner>::array[def::end - def::begin]; 

template <typename def, typename inner> 
bool safe_enum<def, inner>::init = false; 

struct color_def 
{ 
    enum type 
    { 
     begin, red = begin, green, blue, end 
    }; 
}; 

typedef safe_enum<color_def> color; 

template <class Enum> 
void f(Enum e) 
{ 
    std::cout << static_cast<unsigned>(e.underlying()) << std::endl; 
} 

int main() 
{ 
    std::for_each(color::begin(), color::end(), &f<color>); 
    color c = color::red; 
} 
+0

Ceci est juste mon opinion, mais je pense que l'exploitation de la puissance du préprocesseur (avec la bibliothèque Boost.Preprocessor) est un peu plus intuitive. Vous pouvez l'utiliser pour générer toutes sortes de fonctions (mes favoris personnels sont de/à partir de représentations de chaînes et de conversions vers et à partir de nombres entiers). –

Répondre

0

Je n'ai pas regardé le reste du code, mais le « verrouillage revérifié » ne fonctionne pas - si deux threads simultanément vérifier le drapeau pendant qu'il est encore faux? Vous devez utiliser un verrou réel si vous voulez supporter le multithreading.

+0

Je pense que cela avait pour but de dire «assurez-vous d'utiliser un double verrouillage» si vous en avez besoin. –

+0

Je pense que tu as raison :) – Amnon