class HugeTpool{ // Owner of *_dataPool memory
int x;
int y;
// ... etc; // Data Members (many)
size_t* _dataPool; // pointer to huge contiguous data
T_ref operator[](int i){ // used to emulate vector<T> like behaviour
/* Implementation details*/
return T_ref_Obj;
}
};
class T{ // Owner of *_data memory
int a;
// ... etc; // Data Members (few)
size_t* _data; // pointer to small contiguous data
T operator+(T){}
// ... etc; // Member functions
// Glue code to enable interoperability with class T_ref
T operator+(T_ref){}
// ... etc;
};
class T_ref{ // A reference type, to emulate T class interfaces
int a;
// ... etc; // Data Members (Identical to class T)
size_t* _data; // Does not own *_data memory, only references it
T operator+(T_ref);
// ... etc; // Member functions (Identical to class T)
// Glue code to enable interoperability with class T
T operator+(T){}
// ... etc;
};
Here the vector<T>
like interface is being emulated upon the underlying HugeTpool
data structure, with the help of T_ref
class. T
and T_ref
only defer in the management of *_data
memory. The memory pointed to by T_ref
must not be freed upon the destruction of a T_ref
obj. The two classes only defer in copy & move constructors, destructors and assignment operators, and the rest of it is the same.
As T
and T_ref
are in essence the same, I need T
and T_ref
to be interoperable. which is requiring a lot of glue and boilerplate code. Also, as both class have the same interfaces (and member funcitons), there is a lot of code duplication. Is there an elegant to work around this problem? I have considered inheritence, but it does not seem to suit well for this scenario.
This is a simplified version of my problem, in practice, I have many _ref
classes and they need to be interoperable with each other. The glue code required to accomplish this is quickly getting out of control.
It may be that you should be using T &
not T_ref
, or if you need it to be a regular type, std::reference_wrapper<T>
.
If that isn't the case, write a borrow_ptr
template, very similar to unique_ptr
except that it also tracks if it doesn't own it's element. Then use borrow_ptr<size_t> data;
in T
, and discard T_ref
.
As a sketch
template <typename T>
class borrow_ptr
{
std::unique_ptr<T> data;
bool owns;
public:
~borrow_ptr() { if (!owns) data.release(); }
// public surface of unique_ptr
};