2

Here's a dummy example to illustrate:

class C
{
    // complex class with many fields and methods 
    // including very expensive:
    int computeA();
    int computeB();
}

struct S
{
    S(int a, int b); // initializes as {a, b, a*b};
    // how to define below constructor?
    S(const C& c); // Should be equivalent to calling S(c.computeA(), c.computeB())

    int a;
    int b;
    int ab;
}

I'm probably missing something simple but all my attempts are syntactically incorrect. I can obviously circumvent the problem by using a helper function rather than a constructor, but is there a proper way to define such constructor directly?

And of course I don't want to do this:

S(const C& c); // initialize as {c.computeA(), c.computeB(), c.computeA()*c.computeB()};

because of repeating unnecessarily expensive computations.

Julien
  • 13,986
  • 5
  • 29
  • 53
  • there are many errors in your code not related to the question. – 463035818_is_not_an_ai Aug 31 '22 at 09:54
  • Use an initializer list? https://stackoverflow.com/questions/1711990/what-is-this-weird-colon-member-syntax-in-the-constructor – πάντα ῥεῖ Aug 31 '22 at 09:54
  • This is explained in any beginner [c++ book](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) and various SO posts. Refer to [how to ask](https://stackoverflow.com/help/how-to-ask) where the first step is to *"search and then research"* and you'll find plenty of SO related question for this. – Jason Aug 31 '22 at 10:10
  • Thanks all. The usual thing: if you don't know what's the right term to google for, you don't find it... :) – Julien Aug 31 '22 at 10:12
  • Delegating constructors were introduced in C++11, and provide a solution to your problem. If you are using a pre-C++11 compiler, you cannot use constructor delegation. In all versions of C++, it is not necessary to implement a copy constructor at all (in your case) - the compiler-generated definition will suffice. – Peter Aug 31 '22 at 10:40

2 Answers2

9

This code does what you want

S(const C& c) : S(c.computeA(), c.computeB()) {}

It's called a delegating constructor and is available from C++11.

john
  • 85,011
  • 4
  • 57
  • 81
9

You can delegate the constructor:

struct C
{
    int computeA() const;
    int computeB() const;
};

struct S
{
    S(int a, int b) : a(a),b(b),ab(a*b) {}
    S(const C& c) : S(c.computeA(),c.computeB()) {}

    int a;
    int b;
    int ab;
};

There are so many errors in the code you posted that I do not want to list them here, as they aren't really related to the actual question. In at least one case I had to guess what you mean (is const C& right or are the methods correctly non-const, I chose the former).


Fwiw, before delegating constructors were available (C++11) a possible workaround was a static method or free function:

 S make_S(const C& c) {
      return S(c.computeA(),computeB());
 }

With the downside that this is not an implicit conversion. Which can actually be considered as a plus and I would suggest to also make the converting constructor above explicit.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185