Общая перегрузка оператора новая с учетом требований выравнивания - PullRequest
0 голосов
/ 06 ноября 2018

Положение

Я пишу диспетчер памяти для динамического выделения памяти. Чтобы использовать class A при вызове operator new (или delete), достаточно class A наследовать от class CustomAllocate, который сам перегружает new и delete таким образом, что использует диспетчер памяти.

Задача

Однако, по-видимому, я полностью пропустил требования к выравниванию. К сожалению, CustomAllocate::new не имеет информации о том, как class A, наследующий от него, должен быть выровнен, поскольку единственным параметром является размер запрошенной памяти. Я ищу способ включить информацию о выравнивании без необходимости перегрузки newdelete) в каждый class A для использования диспетчера памяти.

Идея 1 (и почему она не работает)

Шаблон class CustomAllocate с целочисленным значением, представляющим требования к выравниванию и наследуемым так: class A : public CustomAllocate< alignof(A) >.

Невозможно, потому что alignof(A) не может быть известно во время его передачи в качестве параметра шаблона, даже если переданный параметр никогда не должен изменять требования выравнивания class A.

Идея 2 (и почему она не работает)

Наличие чисто виртуальной функции virtual int CustomAllocate::getAlignment() = 0, которая реализуется в каждом class A путем вставки копии, например, return alignof(A);.

Невозможно, потому что new является статическим и, следовательно, никогда не сможет получить доступ к виртуальной функции.


Есть рабочие идеи?

1 Ответ

0 голосов
/ 06 ноября 2018

К моему удивлению, похоже, работает следующее:

template <typename T> class CustomAllocate
{
public:
    void* operator new (std::size_t count)
    {
        std::cout << "Calling new, aligment = " << alignof (T) << "\n";
        return aligned_alloc (alignof (T), count);
    }

    void operator delete (void *p)
    {
        std::cout << "Calling delete\n";
        free (p);
    }
};

Тестовая программа:

class A : public CustomAllocate <A>
{
public:
    A (int a, int b) : a (a), b (b) { }
    int a, b;
};

int main ()
{
    A *x = new A (1, 2);
    std::cout << x->a << ", " << x->b << "\n";
    delete x;
}

Выход:

Calling new, aligment = 4
1, 2
Calling delete

Live Demo

...