Date: Fri, 29 Nov 2024 09:27:31 +0100
Hello,
I'm reading the section about dynamic_cast, but I have some difficulties
understanding the rules, especially when the base class is private.
Here is the example code I'm dealing with
I'm reading the section about dynamic_cast, but I have some difficulties
understanding the rules, especially when the base class is private.
Here is the example code I'm dealing with
---- #include <cassert> struct device{virtual ~device() = default;}; struct idevice:device{}; struct odevice:device{}; struct iodevice:idevice,odevice{}; struct middle:iodevice{}; struct derived:private middle{idevice* as_idevice(){return this;}}; // or // struct derived:private iodevice{idevice* as_idevice(){return this;}}; void test_device(idevice* id, bool leaf){ assert(id != nullptr); odevice* iod = dynamic_cast<iodevice*>(id); assert(iod != nullptr); odevice* od = dynamic_cast<odevice*>(id); if(leaf){ assert(od == nullptr); }else{ assert(od != nullptr); } } int main(){ auto d = derived(); test_device(d.as_idevice(), true); auto m = middle(); test_device(&m, false); } ---- It works consistently for gcc, clang and msvc, so I assume they are correct. In expr.dynamic.cast, the standard says ____ The result of the expression dynamic_cast<T>(v) [...] If C is the class type to which T points or refers, the runtime check logically executes as follows: If, in the most derived object pointed (referred) to by v, v points (refers) to a public base class subobject of a C object, and if only one object of type C is derived from the subobject pointed (referred) to by v the result points (refers) to that C object. Otherwise, if v points (refers) to a public base class subobject of the most derived object, and the type of the most derived object has a base class, of type C, that is unambiguous and public, the result points (refers) to the C subobject of the most derived object. Otherwise, the runtime check fails. ___ Since C does not appear in dynamic_cast<T>(v), and T is a type (thus it does not point or refer...), should it maybe be "If C is the class type to which v points or refers"? I fail to see why through idevice* a cast to iodevice* always works, but a cast to odevice* not. Both iodevice* and odevice* are not base classes of idevice*, but iodevice* is a subclass of idevice*. And all those relations are private to derived, but not to idevice and iodevice. What also seems inconsistent, it that it is still possible to always get a odevice* (since iodevice* is a public subclass of odevice*) but one needs to do two conversions: ---- idevice* id = /**/; assert(id != nullptr); odevice* iod = dynamic_cast<iodevice*>(id); assert(iod != nullptr); odevice* od1 = dynamic_cast<iodevice*>(iod); // or even without cast odevice* od1 = iod; assert(od1 != nullptr); ---- Best Federico
Received on 2024-11-29 08:27:37