Я могу придумать два подхода.Во-первых, пусть каждый конструктор для сложной инструкции хранит свой адрес в наборе и проверяет это перед приведением.Во-вторых, если вы можете определить свой собственный распределитель для всех объектов и сохранить необходимое поле тега перед объектом.Я видел, как оба подхода очень успешно использовались в производственном коде.
Вот подход сета:
#include <assert.h>
#include <set>
// Can't be touched!
struct simple_instr
{
};
struct ComplexInstruction : simple_instr
{
ComplexInstruction(const simple_instr& simple) ;
~ComplexInstruction();
bool isHead;
bool isTail;
bool isPreHeader;
};
std::set<simple_instr*> complexInstructions;
ComplexInstruction::ComplexInstruction(const simple_instr& simple) : simple_instr(simple)
{
complexInstructions.insert(this);
}
ComplexInstruction::~ComplexInstruction()
{
complexInstructions.erase(this);
}
ComplexInstruction* tryCast(simple_instr* instr)
{
ComplexInstruction* ret = 0;
if (complexInstructions.find(instr) != complexInstructions.end())
ret = static_cast<ComplexInstruction*>(instr);
return ret;
}
int test()
{
simple_instr si;
ComplexInstruction* siCast = tryCast(&si);
assert(!siCast);
ComplexInstruction ci(si);
ComplexInstruction* ciCast = tryCast(&ci);
assert(ciCast);
return 0;
}
Подход распределителя заключается в следующих строках:
enum InstructionType { eSimple, eComplex } ;
simple_instr* createSimple()
{
// Highly naive - MUST make sure on alignment.
size_t storage = sizeof(InstructionType) + sizeof(simple_instr);
void* raw = malloc(storage);
InstructionType* header = reinterpret_cast<InstructionType*>(raw);
*header = eSimple;
simple_instr* ret = reinterpret_cast<simple_instr* >(header + 1);
return ret;
}
Добавьте свой собственный код для комплекса и обязательно добавьте соответствующие разрушители.
Просто подумал о другом возможном подходе.Возможно, слишком очевидно, и вы уже рассмотрели это, но есть ли какое-либо значение, которое вы можете использовать для simple_instr, чтобы указать, что это действительно сложно?Если это так, вы можете написать:
ComplexInstruction* tryCast(simple_instr* instr)
{
ComplexInstruction* ret = 0;
if (hasComplexFlag(instr))
ret = static_cast<ComplexInstruction*>(instr);
return ret;
}