[cppyy] Auto-downcast objects returned through smart pointers#22586
Conversation
Test Results 21 files 21 suites 3d 10h 44m 38s ⏱️ For more details on these failures, see this check. Results for commit 3a4918e. ♻️ This comment has been updated with latest results. |
aac5660 to
2685f09
Compare
Returning an object by raw pointer already triggers an automatic downcast to its actual (most derived) class, but returning it through a smart pointer (`std::unique_ptr`, `std::shared_ptr`) did not: the object was bound as the declared underlying type, so derived-class members were not accessible. This became more and more of a nuisance as smart pointers become more common in C++ interface. Therefore, this commit implements automatic downcasting also for returned smart pointers. Closes root-project#16210.
Now that also objects returned by smart pointer get automatically downcasted to the actual type, we don't need to dereference returned smart pointer objects to trigger the automatic downcasting.
This commit documents the auto-downcasting for return types of C++
functions, and also improves the structure of the pythonization docs as
follows:
* The term "pythonizations" is very overloaded, so expand the
explanation in the beginning a bit
* Cleanly separate into explanation of pythonization in ROOT, and
later pythonization of use classes. Before, the section on user
pythonization was just labeled "Pythonization example", which was
confusing to me. Will this be an example of a pythonization in ROOT?
* Move the explanation of the user pythonizations to the end, as this
is an advanced feature.
|
Updated! This is how it looks now: |
Automatic downcasting pythonizationIn C++, it is possible to use a base-class pointer to refer to an instance of a class Base {
public:
virtual ~Base() = default;
};
class Derived : public Base {};
Base *foo() {
static Derived obj;
return &obj;
}The same is also possible for smart pointers, like std::unique_ptr<Base> foo_unique() {
return std::unique_ptr<Base>{new Derived};
}Using the p1 = ROOT.foo()
p2 = ROOT.foo_unique()
# if you absolutely need a base class proxy, there is a way:
p3 = ROOT.bind_object(p1, "Base")
print(p1)
print(p2)
print(p3)will give you something like: <cppyy.gbl.Derived object>
<cppyy.gbl.Derived object held by std::unique_ptr<Base>>
<cppyy.gbl.Base object>Note 1: keep in mind that the auto downcasting also affects overload void consume(Base *) {} // overload 1
void consume(Derived *) {} // overload 2In C++, Note 2: while the type of the pointee gets downcast, smart pointer types Note 3: automatic downcasting is not enabled |
vepadulano
left a comment
There was a problem hiding this comment.
Really nice, thanks! Make sure the CI has no related failures before merging 👍
Returning an object by raw pointer already triggers an automatic downcast to its actual (most derived) class, but returning it through a smart pointer (
std::unique_ptr,std::shared_ptr) did not: the object was bound as the declared underlying type, so derived-class members were not accessible.This became more and more of a nuisance as smart pointers become more common in C++ interface.
Therefore, this commit implements automatic downcasting also for returned smart pointers.
Closes #16210.