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_alloc
in 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