How to Write Make_Unique() in VS2012

Is there a way to write make_unique() in VS2012?

You could use Boost.Preprocessor to generate the different parameter counts, but I really don't see the advantage of that. Simply do the grunt job once, stuff it in a header and be done. You're saving yourself compile time and have your make_unique.

Here's a copy-paste of my make_unique.h header that simulates variadic templates for up to 5 arguments.


Since OP seems to not like copy-paste work, here's the Boost.Preprocessor code to generate the above:

First, make a main header that includes the template header multiple times (Boost.Preprocessor iteration code blatantly stolen from this answer):

// make_unique.h
#include <memory>
#include <utility>
#include <boost/preprocessor.hpp>

#ifndef MAKE_UNIQUE_NUM_ARGS
// allow this to be changed to a higher number if needed,
// ten is a good default number
#define MAKE_UNIQUE_NUM_ARGS 10
#endif

#if MAKE_UNIQUE_NUM_ARGS < 0
// but don't be stupid with it
#error Invalid MAKE_UNIQUE_NUM_ARGS value.
#endif

/* optional, see above for premade version
// include premade functions, to avoid the costly iteration
#include "detail/blah_premade.hpp

// generate classes if needed
#if MAKE_UNIQUE_NUM_ARGS > MAKE_UNIQUE_NUM_PREMADE
*/
#define BOOST_PP_ITERATION_LIMITS (0, MAKE_UNIQUE_NUM_ARGS)
#define BOOST_PP_FILENAME_1 "make_unique_template.h"
#include BOOST_PP_ITERATE()
//#endif

And now make a template header that gets included again and again and expands differently depending on the value of MAKE_UNIQUE_NUM_ARGS:

// make_unique_template.h
// note: no include guard

#define N BOOST_PP_ITERATION()

#define MAKE_UNIQUE_TEMPLATE_PARMS \
BOOST_PP_ENUM_PARAMS(N, typename A)

#define MAKE_UNIQUE_FUNCTION_PARM(J,I,D) \
BOOST_PP_CAT(A,I)&& BOOST_PP_CAT(a,I)

#define MAKE_UNIQUE_FUNCTION_PARMS \
BOOST_PP_ENUM(N, MAKE_UNIQUE_FUNCTION_PARM, BOOST_PP_EMPTY)

#define MAKE_UNIQUE_ARG(J,I,D) \
std::forward<BOOST_PP_CAT(A,I)>(BOOST_PP_CAT(a,I))

#define MAKE_UNIQUE_ARGS \
BOOST_PP_ENUM(N, MAKE_UNIQUE_ARG, BOOST_PP_EMPTY)

template<class T BOOST_PP_COMMA_IF(N) MAKE_UNIQUE_TEMPLATE_PARMS>
std::unique_ptr<T> make_unique(MAKE_UNIQUE_FUNCTION_PARMS){
return std::unique_ptr<T>(new T(MAKE_UNIQUE_ARGS));
}

// clean up
#undef MAKE_UNIQUE_TEMPLATE_PARMS
#undef MAKE_UNIQUE_FUNCTION_PARM
#undef MAKE_UNIQUE_FUNCTION_PARMS
#undef MAKE_UNIQUE_ARG
#undef MAKE_UNIQUE_ARGS
#undef N

How to implement make_unique function in C++11?

Copied from make_unique and perfect forwarding (the same is given in Herb Sutter's blog)

template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

If you need it in VC2012, see Is there a way to write make_unique() in VS2012?


Nevertheless, if the solution in sasha.sochka's answer compiles with your compiler, I would go with that one. That is more elaborate and works with arrays as well.

make_unique and perfect forwarding

Herb Sutter, chair of the C++ standardization committee, writes on his blog:

That C++11 doesn’t include make_unique is partly an oversight, and it will almost certainly be added in the future.

He also gives an implementation that is identical with the one given by the OP.

Edit: std::make_unique now is part of C++14.

make_unique does not compile

Variadic templates aren't available in the released version of Visual C++ 11. You can, however, simulate the argument expansion with either lots of copy/paste code for different number of parameters, or use the same compiler tricks used in Microsoft's own implementation of "pseudo-variadics". From this comment on Herb Sutter's blog: http://herbsutter.com/gotw/_102/#comment-6428

#include <memory> // brings in TEMPLATE macros.

#define _MAKE_UNIQUE(TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4) \
\
template<class T COMMA LIST(_CLASS_TYPE)> \
inline std::unique_ptr<T> make_unique(LIST(_TYPE_REFREF_ARG)) \
{ \
return std::unique_ptr<T>(new T(LIST(_FORWARD_ARG))); \
}

_VARIADIC_EXPAND_0X(_MAKE_UNIQUE, , , , )
#undef _MAKE_UNIQUE

Correct use of std::unique_ptr and std::weak_ptr

The information provided is not enough information to solve the lifetime management problem.

You have provided some structure layouts. You have not described how the data in the structures is going to be used, nor anything much about their lifetimes.

Structure layouts does not determine lifetime, except a sane structure layout is going to be a function of the data lifetime problem.

What you have done is said "I have some red paint I want to paint a room with. What house should I buy?" Structure layout is useful to solve lifetime issues, and paint is useful to paint rooms in houses, but providing a structure layout does not tell you what smart pointers to use, and the color of house paint doesn't tell you what house to buy.

You need to think about what the lifetime of the various objects will be, and try to make that as simple as possible, and then use the smart pointers that make that management easy.

Why isn't using #define to hide unique_ptr ugliness working here?

Answer:

Make sure you actually use the macro, and everything will be ok.

Apparently, in an attempt to validate #define macros, VC++ checks your actual use of the macro. If there is no actual use of the macro compiled, VC++ tries to "understand" it, and can throw compiler errors.

Magically, if I add:

pDrawable myDraw = newDrawable();

After my code above, the error disappears.

Sorry for wasting everyone's time. At least this inspired me to read the following article:

http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx

Is there a standard abbreviation for the std::move(std::unique_ptr()) combination?

You mean, you want to write something simpler than this line?

addCallback(std::move(std::unique_ptr<Callback>(new Callback)));  // bleh.

Well, the std::move() is superfluous as you can bind temporaries to rvalue references directly:

addCallback(std::unique_ptr<Callback>(new Callback));

Sadly, there is no std::make_unique() but a make_unique() is easy enough to write:

template <typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&& args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

... which yields

addCallback(make_unique<Callback>());

How emplace_back() works without variadic templates in Visual Studio 2012?

According to this official list of supported C++11 language features, the variadic templates are not supported in VS 2012.

And there is the following note on the same page below:

Variadics: Visual C++ in Visual Studio 2012 had a scheme for
simulating variadic templates. In Visual C++ in Visual Studio 2013,
the simulations are gone and variadics are fully implemented. If your
code relies on the old simulated variadics behavior, you have to fix
it. However, the switch to real variadic templates has improved
compile times and reduced compiler memory consumption.

And on another page there is this note telling how the simulation have been done:

Over the years, we've simulated variadic templates with two different systems of "faux variadic" preprocessor macros - the first
system involved repeatedly including subheaders, while the second
system (more elegant, as far as crawling horrors go) eliminated the
subheaders and replaced them with big backslash-continued macros that
were stamped out by other macros. Functions that were supposed to be
true variadic, like make_shared(args...), were actually implemented
with overloads: make_shared(), make_shared(arg0),
make_shared(arg0, arg1), etc. Classes that were supposed to be
true variadic, like tuple, were actually implemented with
default template arguments and partial specializations. This allowed
us to bring you make_shared/tuple/etc. years ago, but it had lots of
problems. The macros were very difficult to maintain, making it hard
to find and fix bugs in the affected code. Spamming out so many
overloads and specializations increased compile times, and degraded
Intellisense. Finally, there was the infinity problem. We originally
stamped out overloads/specializations for 0 to 10 arguments inclusive,
but as the amount of variadic machinery increased from TR1 through
C++0x's evolution to C++11's final form, we lowered infinity from 10
to 5 in Visual C++ 2012 in order to improve compile times for most
users (we provided a way to request the old limit of 10 through a
macro, _VARIADIC_MAX).

Any metaprogramming way to generate overloads for various numbers of template parameters?

You can try and do the same thing as Boost does, for example in Boost.Function (link to the template header). They use Boost.Preprocessor to enumerate various things on the given number of arguments. For example consider you want to overload a function for 0-2 arguments. The conventional way would be the following:

void foo(){...}
template<class T0>
void foo(T0 a0){...}
template<class T0, class T1>
void foo(T0 a0, T1 a1){...}

Now what Boost does, is to just put those template parameters (class T0 etc) into a preprocessor macro, use that inside the function, and then include the header 3 times for different number of arguments. Example:

// template header, no include guard
#define FOO_TEMPLATE_PARAMS BOOST_PP_ENUM_PARAMS(FOO_NUM_ARGS,class T)
#define FOO_PARAM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
#define FOO_PARAMS BOOST_PP_ENUM(FOO_NUM_ARGS,FOO_PARAM,BOOST_PP_EMTPY)
#if FOO_NUM_ARGS > 0
#define FOO_TEMPLATE template< FOO_TEMPLATE_PARAMS >
#else
#define FOO_TEMPLATE
#endif

FOO_TEMPLATE
void foo(FOO_PARAMS){...}

// cleanup what we've done
#undef FOO_TEMPLATE_PARAM
#undef FOO_TEMPLATE_PARAMS
#undef FOO_PARAM
#undef FOO_PARAMS
#undef FOO_TEMPLATE

The above is the template header, lets call it Foo_Template.h. Now we just include it for the number of arguments we want:

// Foo.h
#include <boost/preprocessor.hpp>
#define FOO_NUM_ARGS 0
#include "Foo_Template.h"
#define FOO_NUM_ARGS 1
#include "Foo_Template.h"
#define FOO_NUM_ARGS 2
#include "Foo_Template.h"
#define FOO_NUM_ARGS 3
#include "Foo_Template.h"
#define FOO_NUM_ARGS 4
#include "Foo_Template.h"
#undef FOO_NUM_ARGS

Perfect! With a little more preprocessor effort and boilerplate "code", we can now overload foo for any number of arguments! The preprocessor macros will expand to something like this:

// with FOO_NUM_ARGS == 0
#define FOO_TEMPLATE_PARAMS /*empty, because we enumerate from [0,FOO_NUM_ARGS)*/
#define FOO_PARAMS /*empty again*/
#define FOO_TEMPLATE /*empty, we got the 0 args version*/

void foo(){...}

// with FOO_NUM_ARGS == 1
#define FOO_TEMPLAtE_PARAMS class T0 /* BOOST_PP_ENUM is like a little for loop */
#define FOO_PARAMS T0 a0
#define FOO_TEMPLATE template< class T0 >

template< class T0 >
void foo( T0 a0 ){...}

// with FOO_NUM_ARGS == 3
#define FOO_TEMPLAtE_PARAMS class T0, class T1, class T2
#define FOO_PARAMS T0 a0, T1 a1, T2 a2
#define FOO_TEMPLATE template< class T0, class T1, class T2 >

template< class T0, class T1, class T2 >
void foo( T0 a0, T1 a1, T2 a2 ){...}

But it's a bliss we won't need this anymore with C++0x thanks to variadic templates. I love 'em.



Related Topics



Leave a reply



Submit