Boost logo

Boost :

From: Andrzej Krzemienski (akrzemi1_at_[hidden])
Date: 2021-03-10 16:13:25


Hi Everyone,
This is part one of my review of Boost.Describe. I will focus only on
dealing with enumerators.

Working with C++ enumerations is harder than one might think, because they
are not what many people believe. They are just a bunch of integral
constants and an integral type. We can get things like this:

enum Season {
    Spring = 1,
    Summer,
    Autumn, // British
    Fall = Autumn, // American
    Winter,
};

struct Human {
   std::string name;
   Season born;
};

int main() {
  Human h {};
  inspect(h);
}

void inspect(Human h) {
  switch(h) {
    case Spring: case Summer: case Fall: case Winter:
      return;
    default:
      assert(false)
  }
}

I can trigger an assertion failure without even doing any cast, because
enums can assume other values that those listed in the declaration.

The low-level interface provided by Boost.Describe is able to manage all
these aspects very nicely. If we call BOOST_DESCRIBE_ENUM on struct Season
above, we will get a list of five elements and the user will have to decide
what she wants to do with it.
On the other hand, requesting that Boost.Describe should provide a higher
level enum-to-string mapping seems to overlook the special rules of C++
enums. How do you want this function to behave if the input enum value is
not found? What do you want the function to do if it finds more than one
corresponding string?

The interface of describe_enumerators<> is optimal.

Macro BOOST_DESCRIBE_ENUM is redundant: BOOST_DESCRIBE_ENUM_CLASS can
handle unscoped enumerations pretty well. Note that in C++11 you can use
the qualified names of unscoped enumerators, like Season::Winter in the
above example.

After playing first with macros for describing structs, I was surprised
that the syntax for describing enumerators doesn't use parentheses for the
list of enumerators:

BOOST_DESCRIBE_ENUM(X, (A, B, C)); // I somehow expected that to work.

Describing enums from the global namespace introduces names starting with
underscore (_enum_descriptor_fn) into global namespace. This is Undefined
Behavior, and is likely to trigger some code sanitizers. Instead use an
ugly name, like boost_describe_enum_descriptor_fn.

I do not appreciate the BOOST_DEFINE_ macros for enumerations. We get as
much as four of them, and neither is able to handle the use case that I
consider basic, which I often have in my code: where I omit value zero and
start from 1:

struct Error {
  badSoething = 1,
  badSomethingElse,
  tooLongSomethng,
  ...
};

So, I am not sure how many real life enums these macros cover.

Regards,
&rzej;


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk