If you really want to use make_shared for your performance benefits, you can still do this:
#include <tuple> #include <memory> #include <redi/index_tuple.h> template<typename X, typename... Args> std::shared_ptr<X> make_shared_TO_THE_MAX(Args&&... args) { struct Wrapper { X x; template<typename... T> Wrapper(std::tuple<T...> targs) : Wrapper(targs, to_index_tuple<T...>{}) { } template<typename T, unsigned... I> Wrapper(T targs, index_tuple<I...>) : x(std::get<I>(targs)) { } }; auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Args>(args)...)); return std::shared_ptr<X>(wrapped, &wrapped->x); }
This combines the constructor arguments into a link tuple and passes it to make_shared , so it doesnβt matter that make_shared cannot handle 10 arguments because it only gets one. Instead of make_shared<X> it uses make_shared<Wrapper> , which allocates space for Wrapper (which is the same size and layout as its member of type X ), and builds it using a tuple of arguments. The Wrapper constructor delegates to another constructor, which extends the tuple to go to the X constructor.
Finally, it uses the shared_ptr anti-aliasing constructor to return shared_ptr<X> , which has ownership of shared_ptr<Wrapper> but retains the address of the X object.
<redi/index_tuple.h> my own header , but I'm trying to get something like that standardized for C ++ 14.
This can be done without variation patterns, but it works more. Here it is for two arguments, just add ten more for twelve!
#include <tuple> #include <memory> template<typename X, typename Arg0, typename Arg1> std::shared_ptr<X> make_shared_TO_THE_MAX(Arg0&& arg0, Arg1&& arg1) { struct Wrapper { X x; template<typename T0, typename T1> Wrapper(std::tuple<T0, T1> targs) : x(std::get<0>(targs), std::get<1>(targs)) { } }; auto wrapped = std::make_shared<Wrapper>(std::forward_as_tuple(std::forward<Arg0>(arg0), std::forward<Arg1>(arg1))); return std::shared_ptr<X>(wrapped, &wrapped->x); }