patterncppMinor
"EnumSpace" - enum inheritance attempt using namespace macro
Viewed 0 times
enumspaceenumattemptinheritanceusingmacronamespace
Problem
EnumSpaceThis file enables the use of a utility I like to call "EnumSpace". This utility is
enums and namespaces combined together in order to create an entity that acts like an enum that is able to inherit and extend an already existing one.It provides three macros for that purpose:
ENUMSPACE_CREATE
ENUMSPACE_EXTEND
ENUMSPACE_END
ENUMSPACE_CREATE should be used to create a new, independent EnumSpace. It receives the name you would like to give your EnumSpace as an argument.ENUMSPACE_EXTEND should be used to extend an already existing EnumSpace. It receives two arguments:- The name of the
EnumSpaceyou would like to inherit.
- The name of the new
EnumSpace.
ENUMSPACE_END should be used like a closing bracket to each of the above.Usage example:
#include ".../enumspace.hpp"
ENUMSPACE_CREATE( First ) ONE ENUMSPACE_END
ENUMSPACE_EXTEND( First, Second ) TWO, THREE, FOUR ENUMSPACE_END
ENUMSPACE_EXTEND( Second, Third ) FIVE, SIX, SEVEN ENUMSPACE_END
ENUMSPACE_EXTEND( Third, Fourth ) EIGHT, NINE, TEN ENUMSPACE_END
int main()
{
std::cout
<< Fourth::ONE
<< Fourth::TWO
<< Fourth::THREE
<< Fourth::FOUR
<< Fourth::FIVE
<< Fourth::SIX
<< Fourth::SEVEN
<< Fourth::EIGHT
<< Fourth::NINE
<< Fourth::TEN;
}Output:
0 2 3 4 6 7 8 10 11 12You probably noticed the inconsistency. The ability to stitch
EnumSpaces comes with a price: it is impossible to retain a straight streak of numbers automatically.[ONE = 0, _last( = 1)]
[_first = _last = 1, 2, 3, 4, _last( = 5)]
[_first = _last = 5, 6, 7, 8, _last( = 9)]
[_first = _last = 9, 10, 11, 12, _last( = 13)]You CAN manually declare the first element you add to be "first" (-> the previous inherited namespace
s "last"):
``ENUMSPACE_CREATE( First ) ONE ENUMSPACE_END
ENUMSPACE_EXTEND( First, Second ) TWO = _first, THREE, FOUR ENUMSPACE_END
ENUMSPACE_EXTEND( Second, Third ) FIVE = _first, S
Solution
You have already identified that it's inconvenient for users to have a gap in their values. That's easily remedied by starting the values immediately after the inherited ones:
A more convenient set of macros would use a variadic argument list to splice the values into the enum, no longer dependent on the user remembering
I think this looks neater where it's used (and it makes Emacs indentation happier than the bare unbraced lists):
One defect that this improved version doesn't address is that we can't specify the integer type underlying the enum, nor use
_first = EnumSpace::_last - 1A more convenient set of macros would use a variadic argument list to splice the values into the enum, no longer dependent on the user remembering
ENUMSPACE_END, and always automatically balanced:#define ENUMSPACE_CREATE(EnumSpaceName, ...) \
namespace EnumSpaceName { \
enum { \
__VA_ARGS__, \
_last \
}; \
}
#define ENUMSPACE_EXTEND(BaseSpace, NewSpace, ...) \
namespace NewSpace { \
using namespace BaseSpace; \
enum { \
_first = BaseSpace::_last - 1, \
__VA_ARGS__, \
_last \
}; \
}I think this looks neater where it's used (and it makes Emacs indentation happier than the bare unbraced lists):
ENUMSPACE_CREATE(First, ONE)
ENUMSPACE_EXTEND(First, Second, TWO, THREE, FOUR)
ENUMSPACE_EXTEND(Second, Third, FIVE, SIX, SEVEN)
ENUMSPACE_EXTEND(Third, Fourth, EIGHT, NINE, TEN)
#include
#include
#include
#include
int main()
{
using namespace Fourth;
std::ranges::copy(std::array{
ONE, TWO, THREE, FOUR, FIVE,
SIX, SEVEN, EIGHT, NINE, TEN
},
std::ostream_iterator(std::cout, ", "));
}0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
One defect that this improved version doesn't address is that we can't specify the integer type underlying the enum, nor use
enum class, with these declarations.Code Snippets
_first = EnumSpace::_last - 1#define ENUMSPACE_CREATE(EnumSpaceName, ...) \
namespace EnumSpaceName { \
enum { \
__VA_ARGS__, \
_last \
}; \
}
#define ENUMSPACE_EXTEND(BaseSpace, NewSpace, ...) \
namespace NewSpace { \
using namespace BaseSpace; \
enum { \
_first = BaseSpace::_last - 1, \
__VA_ARGS__, \
_last \
}; \
}ENUMSPACE_CREATE(First, ONE)
ENUMSPACE_EXTEND(First, Second, TWO, THREE, FOUR)
ENUMSPACE_EXTEND(Second, Third, FIVE, SIX, SEVEN)
ENUMSPACE_EXTEND(Third, Fourth, EIGHT, NINE, TEN)
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
int main()
{
using namespace Fourth;
std::ranges::copy(std::array<int, Fourth::_last>{
ONE, TWO, THREE, FOUR, FIVE,
SIX, SEVEN, EIGHT, NINE, TEN
},
std::ostream_iterator<int>(std::cout, ", "));
}Context
StackExchange Code Review Q#106766, answer score: 3
Revisions (0)
No revisions yet.