Херб Саттер предлагает простую реализацию make_unique()
там: http://herbsutter.com/gotw/_102/
Вот:
template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
Моя проблема заключается в том, что шаблоны с переменными параметрами еще не являются частью VS2012, поэтому я не могу использовать этот код как есть.
Есть ли поддерживаемый способ написать это в VS2012, который бы не включал в себя копирование одной и той же функции с различным количеством аргументов?
Вы можете использовать Boost.Preprocessor для генерации различных параметров, но я действительно не вижу преимущества этого. Просто сделайте грубую работу один раз, поместите ее в заголовок и все будет готово. Вы экономите время компиляции и получаете make_unique
,
ВотКопия моего make_unique.h
заголовок, который имитирует шаблоны с вариациями для 5 аргументов.
Поскольку OP, похоже, не нравится работа копирования-вставки, вот код Boost.Preprocessor для генерации вышеупомянутого:
Во-первых, создайте основной заголовок, который включает заголовок шаблона несколько раз (код итерации Boost.Preprocessor явно украден у этот ответ):
// 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
А теперь создайте заголовок шаблона, который включается снова и снова и расширяется по-разному в зависимости от значения 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
Несмотря на то, что шаблоны variadic не являются частью VS2012, в заголовочный файл встроены макросы <memory>
которые помогают имитировать их.
Увидеть это очень хороший ответ который показывает, как реализовать make_unique<T>
всего за несколько загадочных строк. Я подтвердил, что это хорошо работает:
#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
Единственный способ симулировать функции с помощью списков аргументов с переменным аргументом — создать подходящий список перегрузок. Делается ли это вручную, с использованием чего-то вроде библиотеки препроцессора Boost или с помощью подходящего генератора, все равно: одно и то же: списки действительных переменных аргументов не могут быть смоделированы. Лично я считаю, что наиболее приемлемой версией имитации списков аргументов с переменным числом аргументов является использование компилятора, который поддерживает их в качестве препроцессора, и позволяет генерировать код, подходящий для компиляции компиляторами, но не до поддержки шаблонов с переменным числом аргументов.
Я расширил ответ Хьюга на создание уникальных указателей, которые обертывают массивы (по сути, объединили его с кодом в Эта бумага) и получил следующее, что отлично работает в моих проектах VC2012:
#include <memory>
template<class T> struct _Unique_if {
typedef std::unique_ptr<T> _Single_object;
};
template<class T> struct _Unique_if<T[]> {
typedef std::unique_ptr<T[]> _Unknown_bound;
};
template<class T, size_t N> struct _Unique_if<T[N]> {
typedef void _Known_bound;
};
// Visual Studio 2012 - specific
#define _MAKE_UNIQUE(TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4) \
template<class T COMMA LIST(_CLASS_TYPE)> inline typename _Unique_if<T>::_Single_object make_unique(LIST(_TYPE_REFREF_ARG)) \
{ \
return std::unique_ptr<T>(new T(LIST(_FORWARD_ARG))); \
}
_VARIADIC_EXPAND_0X(_MAKE_UNIQUE, , , , )
#undef _MAKE_UNIQUE
template<class T> inline typename _Unique_if<T>::_Unknown_bound make_unique(size_t n)
{
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[n]());
}
// Visual Studio 2012 - specific
#define _MAKE_UNIQUE(TEMPLATE_LIST, PADDING_LIST, LIST, COMMA, X1, X2, X3, X4) \
template<class T COMMA LIST(_CLASS_TYPE)> typename _Unique_if<T>::_Known_bound make_unique(LIST(_TYPE_REFREF_ARG)) = delete;
_VARIADIC_EXPAND_0X(_MAKE_UNIQUE, , , , )
#undef _MAKE_UNIQUE
Просто из любопытства я попытался сделать подобное — мне нужно было поддерживать больше аргументов, чем 4 — для решения типа _VARIADIC_EXPAND_0X — вероятно, будет поддерживаться только 4.
Вот заголовочный файл MacroArg.h:
#pragma once
//
// Retrieve the type
//
// ARGTYPE( (ArgType) argName ) => ArgType
//
// https://stackoverflow.com/questions/41453/how-can-i-add-reflection-to-a-c-application
//
#define ARGTYPE(x) ARGTYPE_PASS2(ARGTYPE_PASS1 x,)
//
// => ARGTYPE_PASS2(ARGTYPE_PASS1 (ArgType) argName,)
//
#define ARGTYPE_PASS1(...) (__VA_ARGS__),
//
// => ARGTYPE_PASS2( (ArgType), argName,)
//
#define ARGTYPE_PASS2(...) ARGTYPE_PASS3((__VA_ARGS__))
//
// => ARGTYPE_PASS2(( (ArgType), argName,))
//
#define ARGTYPE_PASS3(x) ARGTYPE_PASS4 x
//
// => ARGTYPE_PASS4 ( (ArgType), argName,)
//
#define ARGTYPE_PASS4(x, ...) REM x
//
// => REM (ArgType)
//
#define REM(...) __VA_ARGS__
//
// => ArgType
//
//
// This counts the number of args: (0 is also supported)
//
//
// NARGS( (ArgType1) argName1, (ArgType2) argName2 ) => 2
//
#define NARGS(...) NARGS_PASS2(NARGS_PASS1(__VA_ARGS__))
//
// => NARGS_PASS2(NARGS_PASS1( (ArgType1) argName1, (ArgType2) argName2 ) )
//
#define NARGS_PASS1(...) unused, __VA_ARGS__
//
// => NARGS_PASS2( unused, (ArgType1) argName1, (ArgType2) argName2 )
//
#define NARGS_PASS2(...) NARGS_PASS4(NARGS_PASS3(__VA_ARGS__, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0))
//
// => NARGS_PASS4(NARGS_PASS3( unused, (ArgType1) argName1, (ArgType2) argName2 ) , 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) )
//
#define NARGS_PASS3(_unused,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,VAL, ...) VAL
//
// => NARGS_PASS4(2)
//
#define NARGS_PASS4(x) x
//
// => 2
////
// Show the type without parenthesis
//
// ARGPAIR( (ArgType1) argName1 ) => ArgType1 argName1
//
#define ARGPAIR(x) REM x
//
// => REM (ArgType1) argName1
//
// => ArgType1 argName1
//
//
// Show the type without parenthesis
//
// ARGPAIR( (ArgType1) argName1 ) => ArgType1 && argName1
//
#define REFARGPAIR(x) REFREM x
//
// => REFREM (ArgType1) argName1
#define REFREM(...) __VA_ARGS__ &&
//
// => ArgType1 && argName1
//
//
// Strip off the type
//
// ARGNAME( (ArgType1) argName1 ) => argName1
//
#define ARGNAME(x) EAT x
//
// => EAT (ArgType1) argName1
//
#define EAT(...)
//
// => argName1
//
//
// This will call a macro on each argument passed in
//
// DOFOREACH(typename ARGTYPE, (ArgType1) argName1, (ArgType1) argName2 )
//
#define DOFOREACH(macro, ...) DOFOREACH_PASS1(CAT(DOFOREACH_, NARGS(__VA_ARGS__)), (macro, __VA_ARGS__))
//
// => DOFOREACH_PASS1(CAT(DOFOREACH_, NARGS( (ArgType1) argName1, (ArgType1) argName2 ) ), (typename ARGTYPE, (ArgType1) argName1, (ArgType1) argName2 ) ))
// => DOFOREACH_PASS1(CAT(DOFOREACH_, 2), (typename ARGTYPE, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define CAT(x, y) CAT_PASS1((x, y))
//
// => DOFOREACH_PASS1(CAT_PASS1((DOFOREACH_, 2)), (typename ARGTYPE, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define CAT_PASS1(x) PRIMITIVE_CAT x
//
// => DOFOREACH_PASS1(PRIMITIVE_CAT (DOFOREACH_, 2), (typename ARGTYPE, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define PRIMITIVE_CAT(x, y) x ## y
//
// => DOFOREACH_PASS1( DOFOREACH_2 ), (typename ARGTYPE, (ArgType1) argName1, (ArgType1) argName2 ) ))
//
#define DOFOREACH_PASS1(m, x) m x
//
// => DOFOREACH_2 (typename ARGTYPE, (ArgType1) argName1, (ArgType1) argName2 ) )
//
#define DOFOREACH_0(m)
#define DOFOREACH_1(m, x1) m(x1)
#define DOFOREACH_2(m, x1, x2) m(x1), m(x2)
//
// => typename ARGTYPE( (ArgType1) argName1 ), typename ARGTYPE( (ArgType1) argName2 ) )
// => typename ArgType1, typename ArgType1
//
#define DOFOREACH_3(m, x1, x2, x3) m(x1), m(x2), m(x3)
#define DOFOREACH_4(m, x1, x2, x3, x4) m(x1), m(x2), m(x3), m(x4)
#define DOFOREACH_5(m, x1, x2, x3, x4, x5) m(x1), m(x2), m(x3), m(x4), m(x5)
#define DOFOREACH_6(m, x1, x2, x3, x4, x5, x6) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6)
#define DOFOREACH_7(m, x1, x2, x3, x4, x5, x6, x7) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7)
#define DOFOREACH_8(m, x1, x2, x3, x4, x5, x6, x7, x8) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
#define DOFOREACH_9(m, x1, x2, x3, x4, x5, x6, x7, x8, x9) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9)
#define DOFOREACH_10(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10)
#define DOFOREACH_11(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11)
#define DOFOREACH_12(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12)
#define DOFOREACH_13(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13)
#define DOFOREACH_14(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14)
#define DOFOREACH_15(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14), m(x15)//
// Same version as DOFOREACH, except this one meant to be used for appending list of arguments. If 0 arguments, then list is not appended, otherwise additional command is added in front.
//
#define DOFOREACH2(macro, ...) DOFOREACH_PASS1(CAT(DOFOREACH2_, NARGS(__VA_ARGS__)), (macro, __VA_ARGS__))
#define DOFOREACH2_0(m)
#define DOFOREACH2_1(m, x1) ,m(x1)
#define DOFOREACH2_2(m, x1, x2) ,m(x1), m(x2)
#define DOFOREACH2_3(m, x1, x2, x3) ,m(x1), m(x2), m(x3)
#define DOFOREACH2_4(m, x1, x2, x3, x4) ,m(x1), m(x2), m(x3), m(x4)
#define DOFOREACH2_5(m, x1, x2, x3, x4, x5) ,m(x1), m(x2), m(x3), m(x4), m(x5)
#define DOFOREACH2_6(m, x1, x2, x3, x4, x5, x6) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6)
#define DOFOREACH2_7(m, x1, x2, x3, x4, x5, x6, x7) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7)
#define DOFOREACH2_8(m, x1, x2, x3, x4, x5, x6, x7, x8) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8)
#define DOFOREACH2_9(m, x1, x2, x3, x4, x5, x6, x7, x8, x9) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9)
#define DOFOREACH2_10(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10)
#define DOFOREACH2_11(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11)
#define DOFOREACH2_12(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12)
#define DOFOREACH2_13(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13)
#define DOFOREACH2_14(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14)
#define DOFOREACH2_15(m, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15) ,m(x1), m(x2), m(x3), m(x4), m(x5), m(x6), m(x7), m(x8), m(x9), m(x10), m(x11), m(x12), m(x13), m(x14), m(x15)
//
// ARGX(1) => (Arg1) arg1
//
#define ARGX(index) (Arg##index) arg##index
//
// Defines same function with different amount of arguments.
//
#define DEFINE_MULTIARG_FUNC(macro) \
macro ( ARGX(1) ); \
macro ( ARGX(1), ARGX(2) ); \
macro ( ARGX(1), ARGX(2), ARGX(3) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14), ARGX(15) ); \//
// Same as previous, except add support also of function with no arguments.
// (template functions normally requires at least one template parameter (so you write template<> in front of function and won't get error), that's why separate define)
//
#define DEFINE_MULTIARG_FUNC2(macro) \
macro ( ); \
macro ( ARGX(1) ); \
macro ( ARGX(1), ARGX(2) ); \
macro ( ARGX(1), ARGX(2), ARGX(3) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14) ); \
macro ( ARGX(1), ARGX(2), ARGX(3), ARGX(4), ARGX(5), ARGX(6), ARGX(7), ARGX(8), ARGX(9), ARGX(10), ARGX(11), ARGX(12), ARGX(13), ARGX(14), ARGX(15) ); \
/*
Here is simple example of usage of these macros:
#define MKFUNC_make_unique(...) \
template <class T DOFOREACH2(typename ARGTYPE, __VA_ARGS__) > \
std::unique_ptr<T> make_unique( DOFOREACH(REFARGPAIR, __VA_ARGS__) ) \
{ \
return std::unique_ptr<T>( new T( DOFOREACH(ARGNAME, __VA_ARGS__) ) ); \
}
DEFINE_MULTIARG_FUNC2(MKFUNC_make_unique); //<--
#undef MKFUNC_make_unique
Debugger will stall in "<--" this line, so it makes sense to keep amount of line absolute minimal.
*/
Некоторые подробности по отладке макросов можно найти здесь (обсуждается похожая проблема)
Я знаю, что опаздываю на вечеринку здесь, но я только что столкнулся с этим. Я делал это с помощью однострочного макроса (и совместим с VS2012):
#define MAKE_UNIQUE(T, ...) std::unique_ptr<T>(new T(__VA_ARGS__))
Или менее переносимый, но вы можете передать в пустых параметрах
#define MAKE_UNIQUE(T, ...) std::unique_ptr<T>(new T(##__VA_ARGS__))
Используйте как это:
// MAKE_UNIQUE takes the type followed by the arguments list ...
std::unique_ptr<MyClass> pPointer = MAKE_UNIQUE(MyClass, param_1, param_2, ..., param_n);