how to understand the syntax `Color (&EnumValuesColor())[3] {...}`?

Viewed 49

this is an auto generated header (by flatbuffer serializer) and I've never seen any syntax like Color (&EnumValuesColor())[3] {...} could someone explain it ?

enum Color {
  Color_Red = 0,
  Color_Green = 1,
  Color_Blue = 2,
  Color_MIN = Color_Red,
  Color_MAX = Color_Blue
};

inline const Color (&EnumValuesColor())[3] {
  static const Color values[] = {
    Color_Red,
    Color_Green,
    Color_Blue
  };
  return values;
}
2 Answers
const Color (&EnumValuesColor())[3]

is an old-fashioned way of writing

auto EnumValuesColor() -> Color const (&)[3]

which makes it clearer that EnumValuesColor is a function. To read the return type, we read inside out, and right to left, which gives the return type as: a reference to an array of 3 const Color objects.

It's not surprising that you don't recognise it; this is an example of some very arcane declarator shenanigans we inherited from C, relating to the so-called "spiral rule".

What's happening here is:

  • There is a function called EnumValuesColor
  • It returns a reference to an array of 3 const Colors
  • It's marked inline

You can use https://cdecl.org to help you parse super-complex declarations like this, though note that you'll have to replace Color with int, otherwise it won't know you're talking about a type:

Screenshot of this problem solved for us by cdecl.org

Since C++14, you may prefer to write the function declaration like this instead:

inline auto& EnumValuesColor() {
  static const Color values[] = {
    Color_Red,
    Color_Green,
    Color_Blue
  };
  return values;
}

Now, in such a small function, just by observing that we directly return a const Color values[] (and mentally stick a 3 in there) we can see much more easily what the heck is going on. I am definitely not one of those people who recommends "auto almost always", but this seems like a great use case for it.

As an aside, if you were wondering why bother using a function at all… that's probably to avoid the static initialisation order fiasco. The initialisation of function statics is a gazillion times more predictable than for anything declared at namespace scope.

Related