Конструктор, принимающий shared_ptr

У меня такая ситуация

struct Foo
{
    Foo(int x, int y) : x(x), y(y)
    {
    }
    int x, y;
};

class Bar
{
public:
    typedef std::shared_ptr<const Foo>  ConstFooPtr;
    typedef std::shared_ptr<Foo>        FooPtr;

    Bar(int index = 0, FooPtr ptr = FooPtr()) : index_(index), ptr_(ptr)
    {
    }

private:
    ConstFooPtr ptr_;
    int index_;
};

Я хочу произвести Бар, и 2 метода приходят мне на ум

Bar::FooPtr ptr(new Foo(1, 2)); //1

auto ptr2 = std::make_shared<Bar::FooPtr::element_type>(42, 13); //2

auto bar = Bar(0, ptr);

Первый из них довольно общий, потому что если я буду менять тип FooPtr возможно, мне не придется менять этот код. Но он использует new что плохо, я думаю.

Второй не использует new, но это предполагает, что это shared_ptr что также не является общим.

Есть ли способ заставить его работать и быть общим? Или, может быть, я никогда не должен брать некоторые ptrs в конструкторе?

(Я храню ptr в const Foo потому что я буду делать копии Bar и изменить index_, но data в ptr_ будет то же самое - можно предположить, что Foo что-то большое с некоторыми контейнерами)

1 ответ

Решение

Просто сверните свою собственную версию make_shared и положить его как статический член Bar:

template<typename... Args>
static FooPtr make_shared_foo(Args... args)
{
    return ::std::make_shared<Foo>(::std::forward<Args>(args)...);
}

Таким образом, вы можете сделать указатель так:

auto ptr3 = Bar::make_shared_foo(3,14159);

Конечно, ничто не мешает вам довести это до окончательной версии:

Bar(int index = 0) : index_(index), ptr_(FooPtr())
{ }

template<typename... Args>
Bar(int index, Args... args)
    : index_(index)
    , ptr_(new Foo(::std::forward<Args>(args)...))
{ }

Который просто позволяет передавать аргументы в конструктор Bar который затем направит их, чтобы создать указатель на Foo для собственного потребления.

Другие вопросы по тегам