c++pointersconstructorreference

C++ How to define a member variable that is either passed into or constructed within a constructor


What is a way to define a member object variable of a class that can either be

Basically I would like to have something like this (which does not compile due to trying to bind non-const lvalue reference to temporary):

class A;
class B{
public:
  B() : m_a { A() } {}  // <- does not compile because A() is temporary
  B(A& a) : m_a { a } {}
  useA() { m_a.do_something(); }
private:
  A& m_a;
};

const reference is not an option, since I need access to non-const methods of the object. std::unique_ptr is not an option, because ownership shall stay with the caller of the class's constructor.

Is one of these following options the most reasonable thing to do or is there a better way? Both seem kind of weird. Creating an object m_aObj that is not at all used if the second constructor is used. And using shared_ptrs even though I do not want to keep ownership necessarily.

class A;
class B{
public:
  B() : m_a { m_aObj } {}
  B(A& a) : m_a { a } {}
  useA() { m_a.do_something(); }
private:
  A& m_a;
  A m_aObj;
};
class A;
class B{
public:
  B() : m_a { std::make_shared<A>() } {}
  B(std::shared_ptr<A> a) : m_a {a} {}
  useA() { m_a->do_something(); }
private:
  std::shared_ptr<A> m_a;
};

Solution

  • You can combine a reference A& with an optional internal std::optional<A>.

    class B{
    public:
      B()
        : m_internal_a{ std::in_place }  // Create the internal A
        , m_a { *m_internal_a }          // ... and reference it
      {
      }
    
      B(A& a)
        : m_internal_a{ std::nullopt }   // Omit the internal A
        , m_a { a }                      // ... and reference the external one.
      {
      }
    
      void useA() { m_a.do_something(); }
    private:
    
      std::optional<A> m_internal_a;     // Used only when A is internal
      A& m_a;
    };