0

I have situation like this

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_;
};

I want to produce Bar and 2 methods comes to my mind

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);

The first one is pretty general, because if I will change the type of FooPtr perhaps I will not have to chage this code. But it uses new which is bad I guess.

Second doesn't use new, but it assumes that it is shared_ptr which is not general also.

Is there any method to make it work and be general? Or maybe I should never take some ptrs in constructor?

(I store ptr to const Foo because I will make copies of Bar and change index_, but data in ptr_ will be the same - You can assume that Foo is something big with some containers)

David G
  • 94,763
  • 41
  • 167
  • 253
Prazek
  • 109
  • 1
  • 6

1 Answers1

2

Just roll your own version of make_shared and put it as a static member of Bar:

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

This way you can make you pointer like so:

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

Of course, nothing prevents you from taking this to its ultimate version:

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)...))
{ }

Which just allows you to pass your arguments to the constructor to Bar which will then forward them to create a pointer to Foo for its own consumption.

danielschemmel
  • 10,885
  • 1
  • 36
  • 58