Question

I have a class with two std::unique_ptr members. I want to set those members through the constructor.

Currently I'm doing this:

std::unique_ptr<Assignment> assignment{new Assignment{
       std::unique_ptr<Variable>{new Variable{"a"}},
       std::unique_ptr<Expression>{new Variable{"b"}}
}};

With regular pointers, I would just have done this:

auto assignment = new Assignment{new Variable{"a"}, new Variable{"b"}};
delete assignment;

Can I make the smart pointer version less verbose somehow? I was hoping something like this might work.

std::unique_ptr<Assignment> assignment{new Variable{"a"},{new Variable{"b"}};

However, the constructor of unique_ptr is explicit, so it doesn't.

Was it helpful?

Solution

Is a perfect forwarding constructor an option?

// If you aren't using make_unique, you're doing it wrong.
template <typename T, typename...Args>
inline std::unique_ptr<T> make_unique(Args&&...args) {
    return std::unique_ptr<T>{new T(std::forward<Args>(args)...)};
}

struct Variable {
    std::string name_;

    Variable(std::string name) : name_{std::move(name)} {}
};

struct Assignment {
    std::unique_ptr<Variable> a_, b_;

    template <typename T, typename U>
    Assignment(T&& a, U&& b) :
      a_{make_unique<Variable>(std::forward<T>(a))},
      b_{make_unique<Variable>(std::forward<U>(b))} {}
};

auto assignment = make_unique<Assignment>("a", "b");

Simplifies the syntax quite a bit, IMO.

OTHER TIPS

The easiest solution would probably be

std::unique_ptr<Assignment> assignment {
   new Assignment{Variable{"a"}, Variable{"b"}}};

Of course, that requires a suitable Assignment(Variable&&, Variable&&) overload.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top