0

I have an enum:

enum VehicleType {CAR, BIKE, TRUCK};

The following class uses this enum as a template parameter:

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

Now, I wish to define a class with a map data member that maps a VehicleType to ParkingSlotContainer<VehicleType>. In other words, I want to map CAR to ParkingSlotContainer<CAR>, BIKE to ParkingSlotContainer<BIKE>, etc.

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. It expects ParkingSlotContainer<CAR|BIKE|TRUCK> instead of ParkingSlotContainer<VehicleType>.

What is the right way to define such a map?

9
  • One common work-around is to have a non-template base class (possibly polymorphic), and then use (smart) pointers to the base class as the data. Create objects dynamically and store the pointer. Downcast if needed. Commented Nov 22, 2022 at 11:15
  • 3
    You can't. Thing is that ParkingSlotContainer<CAR> and ParkingSlotContainer<BIKE> and ParkingSlotContainer<TRUCK> are completely different classes. You might consider simply writing ParkingSlotContainer<CAR> carslot; ParkingSlotContainer<BIKE> bikeslot; ParkingSlotContainer<TRUCK> truckslot; Commented Nov 22, 2022 at 11:15
  • By the way, in this case I don't really see the need for a map. Why not simply an array with three elements? Possibly pointers as describe in my previous comment. Or three distinct variables as described by @user253751? Commented Nov 22, 2022 at 11:16
  • The thing with an array or map is that even if you could do it, then because each entry is a completely separate class, what could you even do with the array? You couldn't write array[index].doSomething(); because the compiler wouldn't know which class array[index] was because all of them would be different. Commented Nov 22, 2022 at 11:18
  • ParkingSlotContainer<VehicleType> is not a type, nor is ParkingSlotContainer. The first is a hard error, and the second is a template. Commented Nov 22, 2022 at 11:26

1 Answer 1

1

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.

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. 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...

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the answer. But yes, macros make it harder to read.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.