2017-07-26 2 views
0

Je souhaite que les touches std::map de mon application ne soient pas int s, mais plutôt plus typées comme non modélisées de type enum s définie comme membre d'un struct. Le premier programme ci-dessous montre le concept de la façon dont mon application utilise actuellement map s. Il compile et fonctionne bien.std :: map avec la clé en tant que structure de structure avec le membre enum

#include <map> 

template<int> 
struct NummedMap 
{ 
    typedef std::map< int, NummedMap > NumableMap; 

    NummedMap() {} 

    NumableMap numableMap; 
}; 

int main() 
{ 
    NummedMap<3> numableMap3; 
    NummedMap<4> numableMap4; 
    numableMap3.numableMap[ 3 ] = numableMap3; 
    numableMap4.numableMap[ 4 ] = numableMap4; 

    return 0; 
} 

Le deuxième programme montre comment je voudrais programmer mon application map s, mais je manque quelques concepts concernant les modèles non de type et pourquoi un < enum EnumT > est différent d'un POD int.

#include <map> 

struct Enums1 // a struct containing one kind scoped enums 
{ 
    enum class Action 
    { 
    AAAA, 
    BBBB 
    }; 
}; 

struct Enums2 // a struct containing another kind scoped enums 
{ 
    enum class Action 
    { 
    CCCC, 
    DDDD 
    }; 
}; 

template< enum EnumT > 
struct EnummedMap // a struct containing a map whose key is non-type templateable 
{ 
    typedef std::map< EnumT, EnummedMap > EnumableMap; // error C2065: 'EnumT': undeclared identifier 

    EnummedMap() {} 

    EnumableMap enumableMap; 
}; 

int main() 
{ 
    EnummedMap<Enums1::Action> enummedMap1; // error C2993: illegal type for non-type template parameter 
    EnummedMap<Enums2::Action> enummedMap2; // error C2993: illegal type for non-type template parameter 
    enummedMap1.enumableMap[ Enums1::Action::AAAA ] = enummedMap1; // error C2678: binary '[': no operator found which takes a left-hand operand of type 
    enummedMap2.enumableMap[ Enums2::Action::CCCC ] = enummedMap2; // error C2678: binary '[': no operator found which takes a left-hand operand of type 

    return 0; 
} 

Je ne comprends pas pourquoi la clé de EnumableMap est non, ou pourquoi, par exemple Enums1::Action ne fonctionne pas à peu près comme une clé int.

+0

qu'est-ce que vous essayez d'accomplir? –

+0

«être plus fortement typé» dans un grand programme se traduit par une plus grande clarté du programme, une meilleure vérification des erreurs et, en général, une maintenance du code plus facile. – rtischer8277

Répondre

1
template< enum EnumT > 
struct EnummedMap // a struct containing a map whose key is non-type templateable 
{ 
    typedef std::map< EnumT, EnummedMap > EnumableMap; 

Un paramètre de modèle non de type (dans ce cas, une ancienne ENUM), est une valeur unique, et par définition n'est pas un type, mais std :: carte attend que la clé soit un type, pas une valeur. Pour que cela fonctionne, remplacez "enum" par "typename":

template<typename EnumT > // << *** HERE *** 
struct EnummedMap // a struct containing a map whose key is non-type templateable 
{ 
    typedef std::map< EnumT, EnummedMap > EnumableMap; 
    EnummedMap() {} 

    EnumableMap enumableMap; 
}; 

Cependant, cela permet les types non enum. Si vous voulez éviter toutes les utilisations sauf pour les types ENUM, vous pouvez utiliser un static_assert:

#include <type_traits> 
//... 
template<typename EnumT> 
struct EnummedMap 
{ 
    static_assert(std::is_enum_v<EnumT>); // c++17 
    //static_assert(std::is_enum<EnumT>::value, ""); // c++11 

    typedef std::map< EnumT, EnummedMap > EnumableMap; 
    EnummedMap() {} 

    EnumableMap enumableMap; 
}; 

Ensuite, il ne compilera pas si un non-ENUM est passé comme paramètre de modèle.