Reputation: 6883
I have some C-structures that are used through some algorithms that link together c++ parts.
On the input end there is a c++ structure that inherits from the c structure to add some members. at the output end there are some components that also may require this data.
Is there a safe way to detect if this C structure actually is the mentioned c++ class? maybe by making c++ child classes polymorphic and using dynamic casts?
struct Cstruct{
int someData;
};
class CPPclass: public Cstruct{
CPPclass(){};
int someMoreData;
};
so maybe something like
class CPPclass: public Cstruct{
virtual ~CPPclass(){};
CPPclass(){};
int someMoreData;
};
void test(Cstruct* i_c){
auto cpp = dynamic_cast<CPPclass*>(i_c); // < does not work, because Cstruct is not polymorphic
if(cpp){
// da;
}
}
but maybe?:
class CPPclassHelper: public Cstruct{
virtual ~CPPclassHelper(){};
CPPclassHelper(){};
int someMoreData;
};
class CPPclass: public CPPclassHelper{
virtual ~CPPclassHelper(){};
};
void test(Cstruct* i_c){
auto cpph = static_cast<CPPclassHelper*>(i_c);
auto cpp = dynamic_cast<CPPclass*>(cpph );
if(cpp){
// da;
}
}
Upvotes: 2
Views: 316
Reputation: 238331
You could maintain the type information yourself. Use a static set of all pointers to Cstruct
that are bases of CPPclass
. Insert the base in all constructors of CPPclass
and remove in the destructor. Safe cast can then be implemented using a lookup into that set.
Here is an example:
struct CPPclass: Cstruct{
CPPclass(){
bases.insert(this);
};
CPPclass(const CPPclass&){
bases.insert(this);
};
CPPclass(CPPclass&&){
bases.insert(this);
};
~CPPclass(){
bases.erase(this);
};
static CPPclass* safe_cast(Cstruct* c) {
auto it = bases.find(c);
return it == bases.end()
? nullptr
: static_cast<CPPclass*>(*it);
}
private:
static std::unordered_set<Cstruct*> bases;
};
Usage:
int main() {
CPPclass cpp;
Cstruct c;
Cstruct* ptr_cpp = &cpp;
Cstruct* ptr_c = &c;
std::cout << CPPclass::safe_cast(ptr_cpp) << '\n'; // some address equal to &cpp
std::cout << CPPclass::safe_cast(ptr_c) << '\n'; // null
}
Upvotes: 1