Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有没有办法在VS2012中编写make_unique()?_C++_Templates_C++11_Variadic Templates_Unique Ptr - Fatal编程技术网

C++ 有没有办法在VS2012中编写make_unique()?

C++ 有没有办法在VS2012中编写make_unique()?,c++,templates,c++11,variadic-templates,unique-ptr,C++,Templates,C++11,Variadic Templates,Unique Ptr,Herb Sutter提出了一个简单的make_unique()实现: 这是: template<typename T, typename ...Args> std::unique_ptr<T> make_unique( Args&& ...args ) { return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) ); } 模板 std::unique

Herb Sutter提出了一个简单的
make_unique()
实现:

这是:

template<typename T, typename ...Args>
std::unique_ptr<T> make_unique( Args&& ...args )
{
    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );
}
模板
std::unique_ptr使_唯一(Args&&…Args)
{
返回std::unique_ptr(新的T(std::forward(args)…);
}
我的问题是可变模板还不是VS2012的一部分,所以我不能按原样使用此代码


在VS2012中是否有一种可维护的方法来编写此代码,而不需要复制粘贴具有不同参数计数的相同函数?

您可以使用Boost.Preprocessor来生成不同的参数计数,但我真的看不到这有什么好处。只需做一次咕哝的工作,把它塞进一个标题就可以了。您节省了自己的编译时间,并使您的
成为唯一的

这是我的
make_unique.h
头的复制粘贴,它模拟可变模板,最多可用于5个参数


由于OP似乎不喜欢复制粘贴工作,下面是生成上述内容的Boost.Preprocessor代码:

首先,制作一个多次包含模板头的主头(Boost.Preprocessor迭代代码公然从中窃取):


模拟具有可变参数列表的函数的唯一方法是创建合适的重载列表。无论这是手动完成的,使用类似于Boost预处理器库的东西,还是使用合适的生成器,都是一样的:不能模拟真实的变量参数列表。就我个人而言,我认为模拟变量参数列表最容易维护的版本是使用支持它们的编译器作为预处理器,并让它生成适合编译器编译的代码,而不是支持变量模板。

即使变量模板不是VS2012的一部分,头文件
中内置了一些宏来帮助模拟它们

请参阅其中显示了如何在几行隐晦的代码中实现
使_唯一
。我确认它运行良好:

#include//引入模板宏。
#定义使唯一(模板列表、填充列表、列表、逗号、X1、X2、X3、X4)\
模板\
内联std::unique_ptr make_unique(列表(_TYPE_refrefref_ARG))\
{  \
return std::unique_ptr(新的T(列表(_FORWARD_ARG))\
}
_变量_扩展_0X(使_唯一,,)
#undef使_唯一

我扩展了Hugues的答案,以处理创建包装数组的唯一指针(基本上将其与中的代码合并),并获得了以下结果,这在我的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
#包括
模板结构\u唯一\u如果{
typedef std::唯一的\u ptr\u单个\u对象;
};
模板结构\u唯一\u如果{
typedef std::unique_ptr_Unknown_bound;
};
模板结构\u唯一\u如果{
typedef void_Known_bound;
};
//Visual Studio 2012-特定于
#定义使唯一(模板列表、填充列表、列表、逗号、X1、X2、X3、X4)\
模板内联类型名称\u唯一\u如果::\u单个对象使\u唯一(列表(\u类型\u引用\u参数))\
{                                                                                                                            \
return std::unique_ptr(新的T(列表(_FORWARD_ARG))\
}
_变量扩展0X(_使_唯一,,)
#未定义(undef)使(undef)唯一
模板内联类型名称\u唯一\u如果::\u未知\u绑定使\u唯一(大小\u t n)
{
typedef typename std::remove_extent::type U;
返回std::unique_ptr(新U[n]());
}
//Visual Studio 2012-特定于
#定义使唯一(模板列表、填充列表、列表、逗号、X1、X2、X3、X4)\
模板类型名称_Unique_if::_Known_bound make_Unique(列表(_TYPE_REFREF_ARG))=删除;
_变量扩展0X(_使_唯一,,)
#未定义(undef)使(undef)唯一

出于好奇,我尝试做了类似的事情——我需要支持比4更多的参数——对于一种“可变”的解决方案,可能只支持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.
*/
#pragma一次
//
//检索类型
//
//ARGTYPE((ARGTYPE)argName)=>ARGTYPE
//
// https://stackoverflow.com/questions/41453/how-can-i-add-reflection-to-a-c-application
//
#定义ARGTYPE(x)ARGTYPE_PASS2(ARGTYPE_PASS1 x,)
//
//=>ARGTYPE_PASS2(ARGTYPE_PASS1(ARGTYPE)argName,)
//
#定义ARGTYPE_PASS1(…)(uu VA_ARGS_uu),
//
//=>ARGTYPE_PASS2((ARGTYPE),argName,)
//
#定义ARGTYPE_PASS2(…)ARGTYPE_PASS3(((()
//
//=>ARGTYPE_PASS2(((ARGTYPE),argName,)
//
#定义ARGTYPE_PASS3(x)ARGTYPE_PASS4 x
//
//=>ARGTYPE_PASS4((ARGTYPE),argName,)
//
#定义ARGTYPE_PASS4(x,…)REM x
//
//=>REM(ArgType)
//
#定义REM(…)\uu VA\u参数__
//
//=>ArgType
//
//
//这将统计参数的数量:(也支持0)
//
//
//NARGS((ArgType1)argName1,(ArgType2)argName2)=>2
//
#定义NARGS(…)NARGS_PASS2(NARGS_PASS1(u VA_ARGS_u))
//
//=>NARGS_PASS2(NARGS_PASS1((ArgType1)argName1,(ArgType2)argName2))
//
#定义未使用的NARGS_PASS1(…)、u VA_ARGS__
//
//=>NARGS_PASS2(未使用,(ArgType1)argName1,(ArgType2)argName2)
//
#定义NARGS_PASS2(…)NARGS_PASS4(NARGS_PASS3(uu VA_ARGS_uuu,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
//
//=>NARGS_PASS4(NARGS_PASS3(未使用,(ArgType1)argName1,(ArgType2)argName2),15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0))
//
#定义NARGS密码3(_unused,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,VAL,…)VAL
//
//=>NARGS_PASS4(2)
//
#定义NARGS_PASS4(x)x
//
//  => 2
//
//
//显示不带括号的类型
//
//ARGPAIR((ArgType1)argName1)=>ArgType1 argName1
//
#定义ARGPAIR(x)REM x
//
//=>REM(ArgType1)argName1
//
//=>ArgType1 argName1
//
//
//显示不带括号的类型
//
//ARGPAIR((ArgType1)argName1)=>ArgType1&&argName1
//
#定义重构
#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
#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
#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.
*/
#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);