Closed mutluit closed 1 year ago
I think that's a dynamic_cast
.
Indeed: https://cpp2.godbolt.org/z/EszaoKh1P.
base: type = {
f: (virtual this) = { }
}
derived: type = {
this: base;
}
main: () = {
b: base = ();
[[assert: dynamic_cast<* derived>(b&) == nullptr]]
d: derived = ();
(inout db: base = d) {
[[assert: dynamic_cast<* derived>(db&) != nullptr]]
}
}
I think that's a
dynamic_cast
.
I tried the following using dynamic_cast, but IMO it's not the correct solution. I think there ought to be a better and simpler method, as suggested above.
I have a base class Base_t and multiple derived classes from it (like Dog_t and Cat_t, and so on). I collect the base addresses of these objects in a vector. By using this vector I then need to access the original objects. Not just some virtual functions of the objects, but the complete original object. How best to do this?
The following solution is IMO not that satisfactory.
Is there a better way, maybe in newer C++ standards like c++20? Something like: auto* pDerived = helper(pBase); // pDerived will be a ptr to the correct derived object, or nullptr in case of err
class Base_t { ... class Dog_t : public Base_t { ... class Cat_t : public Base_t { ... ...
enum Type_t { Unknown, Base, Dog, Cat };
struct Identity_t { Type_t Type; union { Base_t pBase; Dog_t pDog; Cat_t* pCat; };
Identity_t() : Type(Unknown), pBase(nullptr) {}
};
Identity_t Identity(Base_t pBase) { Identity_t I; if ((I.pDog = dynamic_cast<Dog_t>(pBase))) { I.Type = Dog; return I; } if ((I.pCat = dynamic_cast<Cat_t*>(pBase))) { I.Type = Cat; return I; } return I; }
// And using it like this: // p is the address of a derived object, ie. Dog_t or Cat_t
auto I = Identity(p); if (I.Type == Dog) { // use I.pDog to access it auto& X = I.pDog; X.print(); } else if (I.Type == Cat) { // use I.pCat to access it auto& X = I.pCat; X.print(); }
... // end of code
I think also it can be expressed with 'as' / 'is' new syntax Like in https://github.com/hsutter/cppfront/issues/411#issuecomment-1533490786 changing to
b: base = ();
[[assert: !(b is derived)]]
d: derived = ();
(inout db: base = d) {
[[assert: (db is derived)]]
}
I think that's a
dynamic_cast
.I tried the following using dynamic_cast, but IMO it's not the correct solution. I think there ought to be a better and simpler method, as suggested above.
Ah, so your suggestion is to reimplement dynamic_cast
.
I think that's out of scope, and definitely unwanted.
If you were to follow the issue template,
you'd find that https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
actually has plenty of guidelines that argue in favor of dynamic_cast
,
and I think counter reimplementations.
It's in fact about extending the language so that it allows that a function can also return auto* or auto&, ie.
auto* func() { // pDog and pCat are different types if (condition) return pDog; return pCat; }
Have you considered std::variant
Also look at this example, which shows direction where cpp2 (and hopefully cpp1) is aiming. That folder with regression tests also contain many useful examples.
In current C++ I'm missing this feature (unless I overlooked something):
auto* pDerived = base2derived(pBase);
pDerived will point either to a derived object, or nullptr if pBase is not the address of a derived.
Is this possible in this new language project?