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 frommy_alloc) ? , or - should I change the definition of
my_allocin order to achieve both the current functionality and the ability to customizestruct 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