1

I've just added Doxygen to my toolset, and whilst I'm comfortable with most of the techniques, I'm a little confused on how I should go about documenting enum flags (also applicable to documentation in general, with or without Doxygen). Given the following class:

class foo
{
   /// @enum  Options
   /// @brief Specifies options for the object. Options are combined using
   ///        the bitwise OR operator e.g. "OPTION1 | OPTION2".
   enum Options
   {
   OPTION1 = 1, //< Option 1 description.
   OPTION2 = 2, //< Option 2 description.
   OPTION3 = 4  //< Option 3 description.
   };

   /// @brief Does something.
   /// @param options  Specifies options.
   void bar(int options) {/* Do something */}
};

How do I go about indicating to the user how to use the options parameter of the bar function? The parameter is of type int, not Options, so there is no direct link between the parameter and the enum. If the parameter was of type Options, then the documentation would link to the description of the enum, which is the behavior I want.

albert
  • 8,285
  • 3
  • 19
  • 32
JBentley
  • 6,099
  • 5
  • 37
  • 72

2 Answers2

2

So make the argument type Options. You can write overloaded operators that return Options to handle & and | and any other logical operators that you need.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
  • I had come across advice that you shouldn't use the enum type for variables which contain the bit flags e.g. [link](http://stackoverflow.com/a/1448404/1227469) – JBentley Nov 29 '12 at 21:47
  • You can't do this unless the enum enumerates all of the possible bit combinations. Jon Bentley's enum is only naming the individual options, not all of the possible ways options can be combined. – David Hammen Nov 29 '12 at 22:12
  • @DavidHammen - sure you can. The underlying type of an ordinary enum is large enough to hold all possible combinations of the defined values, and all combinations of values are valid for the enumeration. 7.2 [dcl.enum]/7 is too long to quote here, but that's what it says. – Pete Becker Nov 29 '12 at 22:46
  • @JonBentley - the problem in the link that you cite is that the code doesn't overload the logical operators, so the enums get promoted to int and the result is an int. If you provide your own overloads you get to return the right type. – Pete Becker Nov 29 '12 at 22:49
  • @PeteBecker - Making the argument an `Options` is undefined behavior if the argument's integral value is not one of the enum values. This won't happen unless you define all possible combinations. That's doable for a small number of options. An enum with 256 values (for example) is quite unwieldy. Compare that to just 8 bit flags. – David Hammen Nov 29 '12 at 23:11
  • @DavidHammen - again, no, it's well defined. See my previous reply, or read 7.2 [dcl.enum]/7. Or read 17.5.2.1.3 [bitmask.types]/2, which explicitly suggests this as an implementation approach for the bitmask types that are defined in the standard library. – Pete Becker Nov 29 '12 at 23:15
  • Here's the next-to-last sentence in 7.2[dcl.enum]/7, which is the same as the last sentence in 7.2[dcl.enum]/6 in C++03: "It is possible to define an enumeration that has values not defined by any of its enumerators." – Pete Becker Nov 29 '12 at 23:21
  • @PeteBecker are you sure? 7.2/5 (as I understand it) says that it is up to the implementation what integral type to give to the enumeration as long as it is large enough to be able to represent any of the enumerators. By definition combining enumerators with | can result in values which are bigger than the largest enumerator, which the implementation is not obliged to handle. 7.2/6 does say you can have non-enumerator values, but it also states that such values are limited to being within the range of the smallest and largest enumerator (which is surely necessary, to comply with 7.2/5). – JBentley Dec 04 '12 at 20:52
  • @JonBentley - yes, I'm sure. This is standard technique, has been for forty years. And, again, the section that specifies this is 7.2/7 in C++11, which clarifies what was always the intention. 7.2/5 (in C++03) says that the underlying type is **an integral type**, not some funky Pascal-like type with a limited range based on the enumerators. If all the enumerators fit, all logical combinations of their bits will fit. – Pete Becker Dec 04 '12 at 23:05
  • @JonBentley - my last sentence, of course, referred to enumerations with only non-negative values. I suppose that's why the extra wording was added. Nevertheless, it's always been required to work. – Pete Becker Dec 04 '12 at 23:18
  • @PeteBecker Yes, after I thought about it I realised that the integral type would have to be large enough to store the bit combinations as well, because you're only changing 0s to 1s, not increasing the size of the data. Thanks for your help - I have spent many hours on this problem and can now move on to other things. – JBentley Dec 05 '12 at 03:42
1

Documenting a variable named options with "Specifies options" is not a meaningful comment. The variable name already says what your existing comment says. So make your comment meaningful:

/// @brief Does something.
/// @param options  Specifies options for the object, which must be a bitwise OR
///                 of zero or more of the bit flags in enum foo::Options.
void bar(int options) {/* Do something */}
David Hammen
  • 32,454
  • 9
  • 60
  • 108
  • 1
    This is more of a debate as to documentation styles, and does not answer my question - perhaps more suited to a comment than an answer. As it happens, I disagree - I've found it highly useful to combine self-documentation with complete commented documentation, as it makes quickly reading through the code much easier months down the line, and writing the comments encourages me to think through the purpose and organization of my code. – JBentley Dec 04 '12 at 18:05
  • 1
    Also, this is not my actual code - I contrived this example in order to ask my question. My real code would provide more context. It's not the content of the comments I'm concerned with, it's how to get the documentation to appear in the right place, so my example focused on that element rather than providing ideal comment content. – JBentley Dec 04 '12 at 18:05