Question

When I pass some flags to a function, only their values are visible in the function call. The programmer has to look up what the values are corresponding to in the function definition. That often means to look at a different location or start typing the function call again for the IDE hints to show up.

// function definition in header file
void foo(bool output = false, bool formatted = false, bool debug = false);

// function call, it is not intuitive what the values mean
foo(true, false, true);

Is there a coding technique to approach this problem? For example, this pseudo code would be more intuitive, but that obviously isn't valid C++.

// function call with explicit mention of flags that should be true
foo(output, debug);

I know that there are many options for explicitly mentioning the options, often with an overhead of needed computation or syntax, like using a std::unordered_map of options. The syntax overhead becomes less with C++11 initializer lists. However, I would like to stick to a common practice if that exists.

Was it helpful?

Solution

In C++11, you could use scoped enumerations:

foo(output::yes, formatted::no, debug::yes);

(If you're stuck in the past, you can do something similar, but less elegant, with regular enumerations).

There's also the old-school method of combining single-bit flag values:

enum {
    output    = 1 << 0,
    formatted = 1 << 1,
    debug     = 1 << 2
};

foo(output | debug);

OTHER TIPS

The way I prefer is simply not to overload on bools in the user interface:

foo( /* non-bool parms ... */);
foo_formatted( /* non-bool parms ... */);
foo_debug( /* non-bool parms ... */);

with perhaps a hidden implementation with overloading as in OP's question.

You could use Named Parameter Idiom.

struct call_foo {

    call_foo& formatted() { formatted_ = true; }
    call_foo& debug()     { debug_     = true; }
    call_foo& output()    { output_    = true; }

    ~call_foo() { foo(output_, formatted_, debug_); }

private:
    bool formatted_ = false;
    bool debug_ = false;
    bool output = false;
};

Usage:

call_foo().debug().formatted();

You can extend it so that methods of call_foo take parameters, too.

I have seen three different ways to handle such situations in differnet coding styles:

  1. Add comments explaining the semantics:

    foo(true /* with output */, false /* not formatted */, debug /* debug on* /);
    
  2. Use a macro which always expands to true and which takes an argument giving the semantics, e.g.

    #define K(Name) true
    
    foo(K(Output), !K(Formatted), K(Debug));
    
  3. Use enums (this requires changing the signature of the function):

    enum OutputMode { WithOutput, WithoutOutput };
    enum FormattingMode { WithFormatting, WithoutFormatting };
    enum DebugMode { WithDebug, WithoutDebug };
    
    foo(WithOutput, WithoutFormatting, WithDebug);
    

If I have to use interfaces like foo, I usually end up with the first version. When designing APIs, I try to avoid having functions taking more than one bool - and if I do want it, I like the third version because it's type safe.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top