C++ make_shared not available
Asked Answered
I

1

5

While I have std::tr1::shared_ptr<T> available in my compiler, I don't have make_shared.

Can someone point me to a proper implementation of make_shared? I see that I need to use varargs to provide arguments to constructor of T.

But I don't have variadic templates available in my compiler as well.

Interstitial answered 3/2, 2012 at 20:34 Comment(9)
Without variadic templates, you'll need multiple versions of make_shared, one for zero arguments, one for one argument, one for two arguments, etc.Agincourt
Which compiler are you using?Stein
@BenVoigt: Variadic templates are not a massive stumbling point, though. The absence of rvalue references makes make_shared less powerful in C++03, but you could still have the single-allocation implementation optimization, as well as the exception-safetly that a factory function provides.Christcross
@Ben: worse: you need two for one argument, four for two arguments, eight for three arguments, etc.Cyndi
@R.MartinhoFernandes: Enlighten me, what varies between the two versions of each argument?Agincourt
you can copy an existing implementations (from boost or compilers supporting the latest standard but not using variadic templates) and use that. I have one lying around but it's msvc only as it depends on their std::tr1::_Ref_count_base and _Enable_sharedVelocity
@Ben: it's T const& vs T&.Cyndi
@R.MartinhoFernandes: Oh, T can be explicitly specified as const something, but won't infer that way? Yeah it looks that way: ideone.com/c3VF8Agincourt
@Ben: exactly. T& will not deduce foo const&, only foo&. That's why Kerrek mentions rvalue references: T&& can deduce both as foo& or foo&&Cyndi
K
6

If your compiler don't give an implementation of make_shared and you can't use boost, and you don't mind the lack of single-allocation optimization both for the object and the reference counter then make_shared is something like this:

Without variadic template support:

// zero arguments version
template <typename T>
inline shared_ptr<T> make_shared()
{
  return shared_ptr<T>(new T());
}

// one argument version
template <typename T, typename Arg1>
inline shared_ptr<T> make_shared(Arg1&& arg1)
{
  return shared_ptr<T>(new T(std::forward<Arg1>(arg1)));
}

// two arguments version
template <typename T, typename Arg1, typename Arg2>
inline shared_ptr<T> make_shared(Arg1&& arg1, Arg2&& arg2)
{
  return shared_ptr<T>(new T(std::forward<Arg1>(arg1),
                             std::forward<Arg2>(arg2)));
}

// ...

If your compiler don't support r-value references, then make 2 versions for each arguments count: one const Arg& and one Arg&

With variadic template support:

template <typename T, typename... Args>
inline shared_ptr<T> make_shared(Args&&... args)
{
  return shared_ptr<T>(new T( std::forward<Args>(args)... ));
}
Kusin answered 3/2, 2012 at 22:12 Comment(1)
Gigi's variadic version also leaves a proper backtrace as discussed here: #9233858Kylynn

© 2022 - 2024 — McMap. All rights reserved.