Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jlschrag/ec2f10776b98a288a0c395ce98fb0481 to your computer and use it in GitHub Desktop.
Save jlschrag/ec2f10776b98a288a0c395ce98fb0481 to your computer and use it in GitHub Desktop.

#define's in C++ code are a terrible way to define collections, but they are commonplace in legacy code. After a few years of refining my approach, this is what I have come up with to replace them.

//Legacy approach (don't do this)
#define BUILDINGTYPE_HOUSE 1
#define BUILDINGTYPE_APARTMENT 4
#define BUILDINGTYPE_OFFICE 9
//buildingType will accept any integer value, even though only 1, 4, & 9 are valid.
void SetBuildingType(int buildingType)
{
//Code inside may compile but could break at runtime.
}
//A better way
namespace BuildingTypes
{
//Typically, explicit enum values are not necessary,
//but they can be helpful when converted legacy #define enumerations to an enum
enum BuildingType
{
House = 1,
Apartment = 4,
Office = 9
};
};
class Consumer
{
private:
BuildingTypes::BuildingType m_BuildingType;
public:
//Use of the enum allows us to strongly-type parameters & return types
//Calling with/returning a value outside of the enum is caught at compile time
BuildingTypes::BuildingType GetBuildingType();
void SetBuildingType(BuildingTypes::BuildingType newType);
}
void Consumer2::Build(BuildingTypes::BuildingType buildingType)
{
//Our using statement is local to the method to avoid polluting the
//global namespace and potentially creating a naming conflict with
//another enum (if another enum had a 'House', for example)
using namespace BuildingTypes;
//We could also put this at the top of the .cpp file if we wanted to use
//it in multiple functions. We could also put it in the header file.
//However, that would apply it everywhere the class was imported.
//...Probably not what we want.
//Notice that because of the using statement, we don't have to use
//case BuildingTypes::BuildingType::House:
//It's already obvious from the variable name above that the cases
//are extended message types.
//The resulting switch is not bloated and is easy for the reader to follow.
switch (buildingType)
{
case House:
BuildHouse();
break;
case Apartment:
BuildApartment();
break;
case Office:
BuildOffice();
break;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment