Search code examples
c++parameters

When calling a C++ function, how to skip several default parameters in uncertain positions?


English is not my native language; please excuse some typing errors. Thanks.

I declare a class named OLEDstream with a constructor like:

OLEDstream::OLEDstream( uint8_t        num, 
                        const uint8_t  *pins,
                        void           (*fAlarm)()  = NULL,
                        int            buffsz       = 21*5,
                        const uint8_t  *font        = u8g2_font_6x10_mr,
                        int            minx         = 0,
                        int            miny         = 11,
                        int            maxx         = 120,
                        int            maxy         = 60,
                        int            stepx        = 6,
                        int            stepy        = 11 );

In some cases, I'd like to change the value of stepy. However, skipping the middle default parameters is not allowed(as far as I know), so I have to pass all the parameters when calling it, even though I just want to change stepy from its default value.

Function overloading seems like a solution, but there are 8 default parameters and it's hard to predict which one users want to change. So I have to overload the function for 100+ times.

Are there some other suggestions, advice or programming skills for the situation?


Solution

  • You've written yourself into a corner with this many parameters. It's not allowed to "skip" default parameters indeed.

    I recommend summing up all the parameters in structs. This would allow specifying only some of the options while relying on the default member initializers for the rest.

    struct Vector { int x, y; };
    
    struct Rectangle { Vector min, max; };
    
    struct OLEDstreamOptions {
        uint8_t num;
        const uint8_t *pins;
        void (*fAlarm)() = nullptr;
        int buffsz = 21 * 5;
        const uint8_t *font = u8g2_font_6x10_mr;
        Rectangle bounds = {0, 11, 120, 60};
        Vector step = {6, 11};
    };
    
    // ...
    OLEDstream(OLEDstreamOptions options) {
        use(options.step.x);
        // ...
    }
    

    Now, leaving some of the options defaulted is easy:

    auto stream = OLEDstream{{ .num = /* ... */, .pins = /* ... */, .step = {10, 20} }};