std :: map with key as templated structs with enum member

时间:2017-07-26 19:37:01

标签: c++ templates enums stdmap non-type

我想让我的应用std::map s'键不是int s,而是更强烈地键入为模板化的非类型enum定义为a的成员struct。下面的第一个程序显示了我的应用当前使用map的方式的概念。它编译并运行正常。

#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;
}

第二个程序显示了我想如何编写应用程序的map,但我遗漏了一些关于非类型模板的概念以及为什么< enum EnumT >与POD {{1}不同}。

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; } 的密钥未声明,或者为什么例如EnumableMap的功能大致不像Enums1::Action密钥。

1 个答案:

答案 0 :(得分:1)

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

非类型模板参数(在本例中为旧式枚举)是单个值,并且根据定义不是类型,但是std :: map期望Key是类型,而不是值。要使其工作,请将“枚举”更改为“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;
};

但是,这允许非枚举类型。如果要阻止枚举类型的所有使用EXCEPT,可以使用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;
};

如果将非枚举作为模板参数传递,则不会编译。