mercredi 28 avril 2021

specializing operator new and operator delete of some class

In order to selectively trace the allocations of particular types, I have created the following construct:

struct my_alloc {
    static void* operator new(size_t sz) { /*...*/ ; return calloc(1,sz); }
    static void operator delete(void *ptr) { /*...*/ ; return free(ptr); }
};

and whenever I wanted to follow the internal allocations of a particular type, say struct A, I could simply inherit from my_alloc:

struct A : my_alloc  
{  
    AImpl* p_impl;
    A() {
        p_impl = new AImpl; // will call my_alloc::operator new
    }
    ~A() {
        delete p_impl;
    }
};

A x();  // x.p_impl has been allocated via my_alloc

This was also useful to trace allocations in std containers:

using Vector = std::vector<some_class, my_alloc>;

Vector v; 
v.reserve(10);   // v.data has been allocated using my_alloc

However, sometimes I need to trace the allocations and I sometimes I don't. To allow that, I tried passing the allocator as a template parameter

template <class ALLOC>
struct A : ALLOC  {   /*...*/   }; 

but it doesn't always do the trick:

using A_alloced = A<my_alloc>;       // works fine
using A_non_alloced = A;             // does not does not compile

I also considered providing a default parameter:

template <class ALLOC = std::allocator>
struct A : ALLOC  {   /*...*/   }; 

but I am missing std::allocator's parameter.

  • Should I change the way I parameterize struct A (perhaps not inherit from my_alloc) ? , or
  • should I change the definition ofmy_alloc in order to achieve both the current functionality and the ability to customize struct A ?

PS: I am looking for a formulation that would also work for the following type-erased class! Note the new Model<B>() call, where Model<T> is not visible outside the class...

class MyType {
    struct Concept {
         virtual ~Concept() = default;
         virtual Concept* clone() const = 0;
    };

    template <class T>
    struct Model {
         T data;

         virtual Concept* clone() const { return new Model(*this); }

         template <class B> 
         Model(B value) : data(value) {}
    };

    Concept *self;
public:
    template <class B>
    MyType(B value) : self(new Model<B>(value)) {}
   
    MyType(const MyType &rhs) : self(rhs.self->clone()) { }
    
};

Aucun commentaire:

Enregistrer un commentaire