макросы — несколько аргументов в C ++ для размещения нового ‘конструктора’

Чтобы выполнить пользовательское отслеживание памяти (предотвращение утечек, обнаружение повреждений), мне нужно использовать новое размещение для создания объектов C ++, что прекрасно работает, но я изо всех сил пытаюсь выяснить, как передать аргументы конструктору, так как он вызывается из макроса (поэтому файл + строка может быть предоставлен автоматически).

Функция:

template <typename T>
T*
cpp_new(
const char *file,
size_t line
)
{
T   *n = (T*)tracked_allocate(&memory_context, sizeof(T), file, line);

if ( n )
{
construct(n);
}
else
{
throw std::bad_alloc();
}

return n;
}

Это вызывается через макрос:

#define new_object(type)    cpp_new<type>(__FILE__, __LINE__)

Размещено новое:

template <typename T>
void
construct(
T *obj
)
{
obj = new (obj) T;
}

Макросы va_list будут охватывать расширение для переменного числа аргументов, только я не хочу указывать количество аргументов, которое имеет конструктор, удаляя va_arg (), и не могу использовать va_start (), так как он ожидает формат.

Это прошло немного над моей головой: http://www.drdobbs.com/cpp/calling-constructors-with-placement-new/232901023?pgno=2

Есть ли способ, которым я могу использовать __VA_ARGS__ из new_object и передать их в функцию построения? У каждого объекта есть только один конструктор, но есть много разных типов объектов, принимающих разные параметры, поэтому я хочу удалить как можно больше ручного обслуживания.

Или есть просто лучший способ сделать то, что я пытаюсь сделать?

2

Решение

Вы не должны иметь дело с конструктом-если-выделение-успешно. Это работа new-expression. Он делает это правильно, как операция, подобная транзакции: либо все успешно выполнено, либо выполняется очистка перед распространением исключения.

Итак, избавившись от этой ответственности, работа вашего макроса заключается в том, чтобы делать то, что могут делать только макросы, а именно подбирать имя файла и строку.

Эти элементы могут / должны быть переданы в функцию распределителя, которая технически является «новым местом размещения», хотя здесь она будет не построить на месте: это размещение нового просто потому, что у него есть дополнительные пользовательские аргументы, например:

bool hopefully( bool const c ) { return c; }

template< class X >
bool throw_( X const& x ) { throw x; }

void* operator new( size_t const size, char const* const filename, int const linenum )
{
void* const p = tracked_allocate( &memory_context, size, filename, linenum );
hopefully( p != 0 )
|| throw_( std::bad_alloc() )
return p;
}

Вам нужно определить соответствующую функцию освобождения места размещения, или же new выражение не сможет освободиться, когда конструктор сгенерирует:

void operator delete( void* const p )
{
// Your custom deallocation.
}

void operator delete( void* const p, char const*, int )
{
::operator delete( p );
}

Теперь вашему макросу просто нужно предоставить соответствующие аргументы размещения, например:

#define SOURCE_LINE_INFO __FILE__, __LINE__

Тогда вы можете просто сказать, как,

new (SOURCE_LINE_INFO) MyType( arg1, arg2, arg3 )

Для более многоразового решения рассмотрите определение struct держать имя файла и номер строки. Затем макрос сводится к созданию экземпляра этого типа и может использоваться более широко. В частности, его можно использовать для регистрации звонков.

4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]