2

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;

}
motiur
  • 1,640
  • 9
  • 33
  • 61
  • 4
    There's absolutely no need for using `new` here. `foo g(3,4);` or `foo g{3,4};` works just fine. And you won't forget calling `delete` like you did. – Quimby Jun 23 '19 at 13:19
  • Related, but not necessarily a dupe: https://stackoverflow.com/questions/56724417/how-can-i-overload-char –  Jun 23 '19 at 14:38

1 Answers1

3

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.

eerorika
  • 232,697
  • 12
  • 197
  • 326
  • Would `std::bind` also technically work for that? I'm not familiar enough with it to know for sure. –  Jun 23 '19 at 14:34
  • 1
    @Chipster you could if you first wrote a function that calls the constructor, but it would be simpler to use a lambda. Even lambda is more complex than the tag dispatch, but if you want to expand an unmodifiable third party class, then a lambda is certainly an option. – eerorika Jun 23 '19 at 14:43