简体   繁体   English

如何声明从 EnumType 到 EnumTypeValue 的 std::map?

[英]How to declare a std::map from EnumType to EnumTypeValue?

I have an enum:我有一个枚举:

enum VehicleType {CAR, BIKE, TRUCK};

The following class uses this enum as a template parameter:以下 class 使用此枚举作为模板参数:

template <VehicleType V>
class ParkingSlotContainer
{
    ...
};

Now, I wish to define a class with a map data member that maps a VehicleType to ParkingSlotContainer<VehicleType> .现在,我希望定义一个 class 和一个 map 数据成员,将VehicleType映射到ParkingSlotContainer<VehicleType> In other words, I want to map CAR to ParkingSlotContainer<CAR> , BIKE to ParkingSlotContainer<BIKE> , etc.换句话说,我想要 map CARParkingSlotContainer<CAR>BIKEParkingSlotContainer<BIKE>等。

This is my attempt:这是我的尝试:

class ParkingFloor
{
private:
    int floor;
    map<VehicleType, ParkingSlotContainer<VehicleType> > slots;
public:
    ParkingFloor(...);
    ...
};

The compiler doesn't accept the above and reports that type name is not allowed .编译器不接受上述内容并报告type name is not allowed It expects ParkingSlotContainer<CAR|BIKE|TRUCK> instead of ParkingSlotContainer<VehicleType> .它需要ParkingSlotContainer<CAR|BIKE|TRUCK>而不是ParkingSlotContainer<VehicleType>

What is the right way to define such a map?定义这样一个 map 的正确方法是什么?

The problem is that you cannot have two values of different type in an std::map : For instance, you cannot have both a ParkingSlotContainer<BIKE> and ParkingSlotContainer<CAR> inside the slots variable, because they are different types.问题是您不能在std::map中拥有两个不同类型的值:例如,您不能在slots变量中同时拥有ParkingSlotContainer<BIKE>ParkingSlotContainer<CAR> ,因为它们是不同的类型。

For these kinds of situations where you want to produce types from enum values, you may want to use higher order macros .对于这些您想从枚举值生成类型的情况,您可能需要使用更高阶的宏 Here is an example of higher order macros applied to your code, where we use them to declare three member variables ( _CAR , _BIKE and _TRUCK ) for the three enum values and then generate overloaded methods setSlot to set a new value to any one of them.这是一个应用于您的代码的高阶宏的示例,我们使用它们为三个枚举值声明三个成员变量( _CAR_BIKE_TRUCK ),然后生成重载方法setSlot以将新值设置为其中任何一个. Just to demonstrate how you can use higher order macros:只是为了演示如何使用高阶宏:

#define FOREACH_VEHICLE_TYPE(OP) \
  OP(CAR) \
  OP(BIKE) \
  OP(TRUCK)

enum VehicleType {
  #define DECL_VEHICLE(name) name,
  FOREACH_VEHICLE_TYPE(DECL_VEHICLE)
  #undef DECL_VEHICLE
};

template <VehicleType V>
class ParkingSlotContainer
{
public:
  int vehicleCount = 0;
};

class ParkingFloor
{
private:
  int floor;
  
#define DECL_SLOT(name) ParkingSlotContainer<name> _##name;
FOREACH_VEHICLE_TYPE(DECL_SLOT)
#undef DECL_SLOT

public:
#define SET_SLOT(name) void setSlot(const ParkingSlotContainer<name>& newValue) {_##name = newValue;}
  FOREACH_VEHICLE_TYPE(SET_SLOT)
#undef SET_SLOT
};

int main() {
  ParkingSlotContainer<BIKE> bikes;
  bikes.vehicleCount = 119;

  ParkingFloor parkingFloor;
  parkingFloor.setSlot(bikes);
  return 0;
}

Depending on your application, this may or may not be overkill.根据您的应用程序,这可能会或可能不会矫枉过正。 It sort of makes the code harder to read...这有点让代码更难阅读......

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM