У меня есть система (C ++), в которой есть много классов, которые имеют требования к переменной памяти (памяти). В большинстве этих случаев размер требуемого хранилища известен при создании объекта и устанавливается на весь срок службы объекта.
Я использую это, например, для создания объекта «String» с полем счетчика, за которым непосредственно следуют реальные символы, встроенные в объект.
class String {
public:
size_t count;
String(size_t count, const char* text) : count(count) {/*...*/}
inline char& at(size_t index) {
return *(reinterpret_cast<char*>(this + 1) + index);
}
void* operator new (size_t size, size_t count) {
return new char[size + count * sizeof(char)];
}
};
class Node {
public:
size_t count;
Node(size_t count, ...) : count(count) {/*...*/}
inline Node*& at(size_t index) {
return *(reinterpret_cast<Node**>(this + 1) + index);
}
void* operator new (size_t size, size_t count) {
return new char[size + count * sizeof(Node*)];
}
};
// ... and several more like this
Я пытаюсь уменьшить это дублирование кода, выделяя поведение «встроенного массива» в общий базовый класс:
template<class T>
class Expando {
size_t count;
Expando(size_t count) : count(count) {}
inline T& at(size_t index) {
return *(reinterpret_cast<T*>(this + 1) + index);
}
void* operator new (size_t size, size_t count) {
return new char[size + count * sizeof(T)];
}
};
Однако, когда я наследую от этого класса:
class String : public Expando<char> {/*...*/}
И перейдите к созданию новой строки:
String* str = new (4) String(4, "test");
GCC пытается использовать мой глобально перегруженный новый оператор вместо оператора в Expando:
inline void* operator new (size_t size, void* mem) { return mem; }
Теперь я мог бы просто продублировать оператор new для каждого из классов (String, Node, ...), но это наполовину проиграет цель рефакторинга.
Есть ли простое решение для этого? Я хотел бы поддерживать данные встроенными в остальную часть класса (чтобы избежать разыменования и выделения кучи), а также избежать нестандартных расширений (таких как массивы нулевого размера в конце классов). В то же время я хотел бы уменьшить дублирование.