4

I have a function f returning a pair of objects of classes A and B:

auto f() -> std::pair<A,B>;

Furthermore, I have a class C that has A and B as members:

class C {
  public:
    C();
  private:
    A a;
    B b;
};

In the constructor of C, I want to use the member initalizer list and initialize with the output of f:

C(): a(f().first), b(f().second) {}

This calls f twice though and it is a quite complicated function. Is there a way to achieve this using the member-initializer list without calling f twice? The internal structure of C can unfortunately not be changed.

Henk
  • 826
  • 3
  • 14

2 Answers2

5

Improving on the idea from AnkitKumar's answer:

class C
{
    A a;
    B b;
    
    C(std::pair<A,B> &&pair) : a(std::move(pair.first)), b(std::move(pair.second)) {}

  public:
    C() : C(f()) {}
};
HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • 3
    Nice! This construction in particular enables to basically create a temporary in the member intializer list. – Henk Feb 06 '22 at 18:02
  • If there is another function `g(A a)` dependent on `a` for initializing `C` and `D` with the returned `pair` another constructor 'level' can be introduced. Alternatively `f` can return a quadruple of `A`, `B`, `C`, `D` with just one constructor 'level'. This would also be the only way, if complicated program flow is involved. So every function can be translated into initializer lists without introducing additional members for storing temporaries. – Sebastian Feb 06 '22 at 18:52
2

One possible solution:

class C {
  public:
    C(std::pair<A,B>);
  private:
    ...
};

C(pair<A,B> p): a(p.first), b(p.second) {}

You'll now call f only once, which will work so long as it doesn't contradict some other requirements.

Ankit Kumar
  • 1,145
  • 9
  • 30