Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delegate constructor and default argument depending on other arguments

I have a constructor for B with some default argument depending on other arguments:

struct A
{
    int f();
    A(const A&) = delete;
    A(A&& );
    // ....
};

struct B
{
    B(A a, int n=a.f()) {//...}
    // ...
};

This clearly does not work in that way, so I want use a delegate constructor:

struct B
{
      B(A a, int n) {//...}
      B(A a): B(a, a.f()) {}
};

This, however, also does not work because the copy constructor of A is deleted. So I need something like

struct B
{
      B(A a, int n) {//...}
      B(A a): B(std::move(a), a.f()) {}
};

As far as I know, however, there is no guarantee that a.f() is evaluated before std::move, so the result is undefined. Is there a possiblity to get the value of a.f() before std::move or should I better write two seperate constructors?

like image 691
Helmut Zeisel Avatar asked Jan 12 '19 09:01

Helmut Zeisel


2 Answers

Why don't you do something simpler - i.e. overload your constructor?

struct B
{
    B(A a) {
        int n = a.f();
        ...
    }
    B(A a, int n) {
        ...
    }
};

If you don't like repetition of your code in ..., you can always have just a single call to a private member function that does the rest of the construction.

like image 132
CygnusX1 Avatar answered Sep 22 '22 00:09

CygnusX1


The are more possible solutions for this.

  1. The most simple approach is to make a a pointer:

    struct B
    {
         B(A* a, int n) {...}
         B(A* a): B(a, a->f()) {}
    };
    
  2. A more complex approach is to try to make a a reference:

    struct B
    {
          B(A& a, int n) {...}
          B(A& a): B(a, a.f()) {}
    };
    

I would not suggest this solution. The pointer is a cleaner approach.

Edit:

  1. Via std::move from the utility libary

    struct B
    {
          A&& a:
          int n:
    
          B(A&& a, int n): a(std::move(a)), n(n) {...}
          B(A&& a): B(std::move(a), a.f()) {...}
    };
    
like image 26
vikkre Avatar answered Sep 25 '22 00:09

vikkre