Initialize parameter into constructor, other than the first one

Viewed 66

I want to explicitly change the second parameter in a constructor of a struct, in the following scenario. Is it possible, if so, how?

struct foo{
    int x;
    int y;
    foo(int a=4, int b=6){
        x=a;
        y=b;
    }
};

int main(){
    foo *f = new foo();
    cout<<f->x<<" "<<f->y<<endl;
   //4 6 
    foo *g = new foo(3,4);
    cout<<g->x<<" "<<g->y<<endl;
    //3 4
    foo *h = new foo(3);
    cout<<h->x<<" "<<h->y<<endl;
   //3 6
   //Can something like this be 
   //done in C++, if I want
   //to change the value of the 
   //second variable only
    foo *k = new foo(b = 13);

return 0;

}
1 Answers

Is it possible, if so, how?

It is not possible with constructor. In general, c++ does not support named keyword arguments to functions, and it is not possible to skip arguments even if they have a default, if you want to pass a non-default after it.

It will be possible without constructor using list initialisation syntax since C++20 using designated initialisers, if you use default member initialisers:

struct foo{
    int x = 4;
    int y = 6;
};

int main(){
    foo f {.y = 4};
}

You can achieve something similar with tag dispatching; No need for future standard:

struct foo{
    int x = 4;
    int y = 6;

    enum Xtag { Xinit };
    enum Ytag { Yinit };

    foo(int a, int b) : x(a), y(b) {}
    foo(Xtag, int a)  : x(a) {}
    foo(Ytag, int b)  : y(b) {}
};

int main(){
    foo f(foo::Yinit, 4);
}

A solution using lambda that can be used without modifying an existing class. Following works with your definition of foo:

auto make_foo_x4 = [](int b) {
    return foo(4, b);
};
foo f = make_foo_y(4);

The downside is that we have to explicitly repeat the default value of x, so this can break assumptions if the default is changed in class definition.

Related