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

前端 未结 6 1337
情书的邮戳
情书的邮戳 2020-12-03 07:44

Herb Sutter propose a simple implementation of make_unique() there: http://herbsutter.com/gotw/_102/

Here it is:

template

        
相关标签:
6条回答
  • 2020-12-03 08:22

    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.

    0 讨论(0)
  • 2020-12-03 08:30

    I know I am late to the party here, but I just came across this. I have been doing this with a one-liner macro (and is VS2012 compatible):

    #define MAKE_UNIQUE(T, ...) std::unique_ptr<T>(new T(__VA_ARGS__))
    

    Or less portable, but you can pass in empty params

    #define MAKE_UNIQUE(T, ...) std::unique_ptr<T>(new T(##__VA_ARGS__))
    

    Use like this:

    // MAKE_UNIQUE takes the type followed by the arguments list ...
    std::unique_ptr<MyClass> pPointer = MAKE_UNIQUE(MyClass, param_1, param_2, ..., param_n);
    
    0 讨论(0)
  • 2020-12-03 08:31

    I have extended Hugues's answer to handle creating unique pointers which wrap arrays (basically merged it with the code in this paper) and obtained the following, which works fine in my VC2012 projects:

    #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
    
    0 讨论(0)
  • 2020-12-03 08:40

    Just out of curiosity I have tried to make similar thing - I needed to support more arguments than 4 - for _VARIADIC_EXPAND_0X kind of solution - probably only 4 will be supported.

    Here is MacroArg.h header file:

    #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.
    */
    

    Some of details on debugging macros can be found here (similar kind of problem being discussed)

    How can I add reflection to a C++ application?

    0 讨论(0)
  • 2020-12-03 08:42

    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
    
    0 讨论(0)
  • 2020-12-03 08:43

    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
    
    0 讨论(0)
提交回复
热议问题