A common class of dispensers without variable patterns?

I am trying to write a general dispenser class that does not actually free the memory of the object when it is free () 'd, but holds it in the queue and returns the previously allocated object if a new one is requested. Now I can’t turn my head around how to pass arguments to the constructor of the object when using my dispenser (at least without resorting to variational patterns, that is). The alloc () function came out, which looks like this:

template <typename... T>
inline T *alloc(const &T... args) {
    T *p;

    if (_free.empty()) {
        p = new T(args...);
    } else {
        p = _free.front();
        _free.pop();

        // to call the ctor of T, we need to first call its DTor
        p->~T();
        p = new( p ) T(args...);
    }
    return p;
}

However, I need code for compatibility with today's C ++ (and older versions of GCC that do not support variable templates). Is there any other way to pass an arbitrary number of arguments to an object constructor?

+3
2

pre-++ 0x, , :

template<class T> 
T* alloc() { 
    /* ... */ 
}

template<class T, class A0> 
T* alloc(const A0& a0) { 
    /* ... */ 
}

/* ... */

, , . Boost.Preprocessor script.

Boost.PP:

#include <boost/preprocessor/arithmetic/inc.hpp>
#include <boost/preprocessor/repetition/enum_binary_params.hpp>
#include <boost/preprocessor/repetition/enum_params.hpp>

template<class T>
T* alloc() {
    return new T;
}

#define FUNCTION_ALLOC(z, N, _) \
  template<class T, BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), class T)> \
  T* alloc(BOOST_PP_ENUM_BINARY_PARAMS_Z(z, BOOST_PP_INC(N), const T, &p)) { \
     return new T( \
       BOOST_PP_ENUM_PARAMS_Z(z, BOOST_PP_INC(N), p) \
     ); \
  }

BOOST_PP_REPEAT(10, FUNCTION_ALLOC, ~)

#undef FUNCTION_ALLOC

alloc() 10 .

+3

-++ 11 , alloc, . ++ 03 20 . , :

template <typename T>
inline T *alloc(const &T arg) {
    T *p;

    if (_free.empty()) {
        p = new T(arg);
    } else {
        p = _free.front();
        _free.pop();

        // to call the ctor of T, we need to first call its DTor
        p->~T();
        p = new( p ) T(arg);
    }
    return p;
}

:

// copy construct T into the allocator memory:
instance_of_your_allocator.alloc(T(1, 2, 3));

, - .

:

vector<T> vec;
vec.push_back(T(1, 2, 3)); // C++03 way, uses move cons-tor in C++11 if possible.
vec.emplace_back(1, 2, 3); // C++11 way, constructs in-place
0

Source: https://habr.com/ru/post/1740318/


All Articles