Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defaulting multiple arguments

Tags:

c++

I have a class that looks like the following:

class Example {
  Foo1 f1;
  Foo2 f2;
  Foo3 f3;
  size_t hash;
};

Please note that FooX will be always different classes. I want to add a constructor which assigns the value to each fX element and computes the hash (for cacheing its value).

However I want to be able to omit any number of arguments and assign a default value to the corresponding member of the class. Obviously I could use the defaulting feature of C++: Example(Foo1 f1 = DEFAULT4F1, Foo2 f2 = DEFAULT4F2, Foo3 f3 = DEFAULT4F3); However for being able to omit f2, I need to omit f3, which I might want to specify. Then I could write a constructor for each possible order, but the amount of constructors grows with the factorial of elements, so for this case:

Example(Foo1 f1 = DEFAULT4F1, Foo2 f2 = DEFAULT4F2, Foo3 f3 = DEFAULT4F3);
Example(Foo1 f1 = DEFAULT4F1, Foo3 f3 = DEFAULT4F3, Foo2 f2 = DEFAULT4F2);
Example(Foo2 f2 = DEFAULT4F2, Foo1 f1 = DEFAULT4F1, Foo3 f3 = DEFAULT4F3);
Example(Foo2 f2 = DEFAULT4F2, Foo3 f3 = DEFAULT4F3, Foo1 f1 = DEFAULT4F1);
Example(Foo3 f3 = DEFAULT4F3, Foo1 f1 = DEFAULT4F1, Foo2 f2 = DEFAULT4F2);
Example(Foo3 f3 = DEFAULT4F3, Foo2 f2 = DEFAULT4F2, Foo1 f1 = DEFAULT4F1);

I don't want to specify the same constructor that many cases, because in my real case there are more than 3 parameters. I also want to consider forwarding their values (Foo&& arg and std::forward(arg))

Edit: To sum up: desired constructor would act like this, but being able to omit any of the parameters, and use a default value for them

Example(Foo1&& f1, Foo2&& f2, Foo3&& f3) :
  f1(std::forward(f1)),
  f2(std::forward(f2)),
  f3(std::forward(f3)),
  hash(doSomethingForIt())
{
}

like image 205
oierlauzi Avatar asked Jan 26 '23 22:01

oierlauzi


1 Answers

This is a workaround, not an initialization in C++ sense.

Because you need in advance all members of your class, you already know them:

class Example {
  Foo1 f1;
  Foo2 f2;
  Foo3 f3;
  size_t hash;
  //default ctor, initializes all members with defaults defined somewhere
  Example() : f1(defaultF1), f2(defaultF2), f3(defaultF3) {}
....

Now we add setters:

  Example& setFoo1(Foo1 fo1 = defaultF1)
  {
      f1 = fo1;
      return *this;
  }

  Example& setFoo2(Foo2 fo2 = defaultF2)
  {
      f2 = fo2;
      return *this;
  }
....

}; //class Example

And then the usage:

Example exple;
exple.setFoo2(someF2value).setFoo1(someF1value); //not all setFooX are used

Notice that we can call setFooX() in any order.

like image 191
Ripi2 Avatar answered Feb 05 '23 09:02

Ripi2