Herb Sutter propose a simple implementation of make_unique()
there: http://herbsutter.com/gotw/_102/
Here it is:
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
My problem is that variadic templates are not yet part of VS2012, so I can't use this code as is.
Is there a maintainable way to write this in VS2012 that wouldn't involve copy-pasting the same function with different args count?
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
Even though variadic templates are not part of VS2012, there are macros built into the header file <memory>
that help simulate them.
See this very nice answer which shows how to implement make_unique<T>
in just a few cryptic lines. I confirmed that it works well:
#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
The only way to simulate functions with variadic argument lists is by creating a suitable list of overloads. Whether this is done manually, using something like the Boost preprocessor library, or using a suitable generator all amounts to the same: real variadic argument lists cannot be simulated. Personally, I think the most maintainable version of simulating variadic argument lists is to use a compiler which supports them as preprocessor and have it generate code suitable to be compiled by compilers not, yet, up to support variadic templates.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With