Skip to main content
added 151 characters in body
Source Link
Toby Speight
  • 81.7k
  • 14
  • 101
  • 308
 

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 <algorithm>
#include <array>
#include <iostream>
#include <iterator>

int main()
{
    using namespace Fourth;
    std::ranges::copy(std::array<int, Fourth::_last>{
            Fourth::ONE, Fourth::TWO,
            Fourth::THREE, Fourth::FOUR,
            Fourth::FIVE, Fourth::SIX,
            Fourth::SIX, SEVEN, Fourth::EIGHT,
            Fourth::NINE, Fourth::TEN
        },
        std::ostream_iterator<int>(std::cout, ", "));
} 


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.

I think this looks neater where it's used:

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()
{
    std::ranges::copy(std::array<int, Fourth::_last>{
            Fourth::ONE, Fourth::TWO,
            Fourth::THREE, Fourth::FOUR,
            Fourth::FIVE, Fourth::SIX,
            Fourth::SEVEN, Fourth::EIGHT,
            Fourth::NINE, Fourth::TEN
        },
        std::ostream_iterator<int>(std::cout, ", "));
}
 

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 <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, ", "));
} 


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.

Source Link
Toby Speight
  • 81.7k
  • 14
  • 101
  • 308

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:

 _first = EnumSpace::_last - 1

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

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()
{
    std::ranges::copy(std::array<int, Fourth::_last>{
            Fourth::ONE, Fourth::TWO,
            Fourth::THREE, Fourth::FOUR,
            Fourth::FIVE, Fourth::SIX,
            Fourth::SEVEN, Fourth::EIGHT,
            Fourth::NINE, Fourth::TEN
        },
        std::ostream_iterator<int>(std::cout, ", "));
}
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,