Ward
Ward

Reputation: 799

make_unique cannot access private constructor in static member

My class has the following structure:

class S {
  public:
    S() {}
};

class T {
  private:
    std::unique_ptr<S> a;
    T(S);

  public:
    static std::unique_ptr<T> make_item() {
        std::unique_ptr<S> s_instance = std::make_unique<S>();
        return std::make_unique<T>(std::move(s_instance));
    }
};

However, when I try to make a unique_ptr in the make_item, it sees the constructor as private.

Is there a way to allow the use of the private constructor in a static member function of the class itself? Because one member is a unique_ptr to S (a rather heavy object), we wish not to use a copy.

Upvotes: 17

Views: 14495

Answers (2)

Ward
Ward

Reputation: 799

As proposed by yksisarvinen in the comments, a way to solve this is to just replace make_unique<T> by std::unique_ptr<T>(new T(S)).

class S {
  public:
    S() {}
};
class T {
  private:
    std::unique_ptr<S> a;
    T(S);

  public:
    static std::unique_ptr<T> make_item() {
        // Create S
        std::unique_ptr<S> s_instance = std::make_unique<S>();
        return std::unique_ptr<T>(new T(s_instance));
    }
};

Upvotes: 25

AshkanVZ
AshkanVZ

Reputation: 778

It is possible to either declare make_unique and its internal helpers (if any) a friend function, which make the code non-portable (as said here: How to make std::make_unique a friend of my class)

Or make the constructor public but add a private element to its arguments, for example:

class S {
  public:
    S() {}
};

class T {
  private:
    struct Private
    { 
      friend T;
      private:
        explicit Private() = default; 
    };

    std::unique_ptr<S> a;

  public:
    T(S s, Private);

    static std::unique_ptr<T> make_item() {
        auto s_instance = std::make_unique<S>();
        return std::make_unique<T>(std::move(s_instance), Private());
    }
};

Upvotes: 4

Related Questions