-
Notifications
You must be signed in to change notification settings - Fork 586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add of for downcasting when c-style cast cannot work #700
Conversation
What's wrong with doing it in a way like pull #554 ? |
I'm not entirely sure I understand what you're trying to do here, but it's obviously more complicated than it needs to be. I'll let you go through a few iterations of this until you settle on something that makes more sense. |
I was probably not clear enough. What don't you understand in the purpose of this PR ? |
Among probably other things, I think we can get away with only dynamic_cast, and if we do that, how much does it simplify? |
As said above, dynamic_cast won't work for non-polymorphic base class. So in the case of simple multiple inheritance, like in the example of the top post, downcasting a B2 to a D needs a static_cast: Compiling this: struct B1 {
int i;
};
struct B2 {
int j;
};
struct D: public B1, public B2 {
int k;
};
int main(int ac, char **av) {
D *d = new D();
B2 *b2 = d;
d = dynamic_cast<D*>(b2);
} fails with:
|
I see, so there's too many types of casts to try and force this into never ending flags. How about we add an Info that would let users specify the name of the cast function (ehem, operator) they want to use for this? |
The PR implements the needed logic to make the right choice between static_cast and dynamic_cast automatically, without needing info (but the new polymorphic info, added for good measure, but which may well be never used). Using an explicit info as you suggest would work, but why request that from the user when the parser can detect what to do by itself ? To save about ~ 10 new lines of code in parser ? |
So let's remove that flag entirely until it's necessary somehow for someone somewhere? |
polymorphic ? Ok, as you wish. |
But this behavior shouldn't be enabled by default. It only happens on Info.upcast right? That's a bit weird.. Anyway, from() sounds better than of() for that kind of operation: |
Which behavior ? The generation of the of/from methods ?
You must be right. However I think the best would be a constructor, as said in the last note or the top post. Any opinion or idea about that ? |
The |
I suppose you could add new constructors like you proposed? It creates a temporary wrapper object, but it can't hurt.
Meh, Info.upcast is fine, let's not add anything more just for this. Ideally we'd want to always do all of that upcasting and downcasting I suppose, but for backward compatibility, let's just make sure upcast() doesn't get called without Info.upcast. |
Ok. I guess we could add support for
The current upcast() is already called both for multiple inheritance and |
Sounds reasonable,
No, I mean it shouldn't generate anything, unless the class has the Info.upcast flag explicitly set by the user. |
Do you prefer I look into this and try to make a PR, or will you do it yourself ?
I don't get it. |
It shouldn't be too hard, but it's not something I'll be doing myself, no...
Right, ok, so let's say, if doesn't break anything with the presets, we can leave like that, sounds good? |
Leave the PR as is ? Sure. |
We probably only need to update this line: |
Right. That's what I did. However, there is a little complication. Could you advise about it ? Currently, when
where Here we want, in addition, to annotate with something like What would be the best way to inform the generator about this ? |
I'm not sure I follow, I didn't write that code. You're the one that added
support for that, so do whatever it needs to do?
|
Ok.
Rather than:
I'll prepare a PR about that, but this will not be before the end of the week. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good to merge! Anything else you'd like to change before that though?
Nothing I can think of. |
The
asB()
method generated by the Parser allows to upcast an instance of a classD
to an instance of one of its base classB
in the cases where C-style pointer cast (as used for instance in pointer cast constructorsB(Pointer)
does not work.This is useful for multiple inheritance and for virtual inheritance from a polymorphic class.
But we lack the equivalent downcast.
In Java,
D
extendsB1
and has aasB2()
method.But if we have an instance
b2
ofB2
that we know is aD
, we have no way to cast it to an instance ofD
.new D(b2)
will lead to a segmentation fault.For polymorphic classes, here is an example from Pytorch:
LinearImpl
extendsModule
(throughLinearImplCloneable
). Say we get a instance ofModule
from one of the many functions of libtorch returning a Module, we know it's aLinearImpl
, and we need to call itsforward
function. We cannot.new LinearImpl(module).forward(tensor)
triggers a segmentation fault (see issue bytedeco/javacpp-presets#1393).This PR adds a static
of(B)
method, along with theasB()
method, to perform the downcast. This static method does astatic_cast
/static_pointer_cast
or adynamic_cast
/dynamic_pointer_cast
. The C++ rules that determine which casting flavor to use are as follows:These rules imply that downcasting is not possible (without hacks we won't address) if inheritance is virtual but the base class is not polymorphic.
Virtual inheritance can be reliably detected by the parser.
Polymorphism can be detected too, but not reliably since a class can inherit virtual members from a class defined in a non-parsed, or non-parsed-yet, header.
This PR also adds these detections to determine if downcast can be performed and which flavor to use. It also adds a
polymorphic
info to label a class as polymorphic when the Parser cannot detect it.Not that
upcast
info is still needed because we most certainly need this information before we parse the subclass that declares a virtual inheritance and we realizeupcast
is needed. However I added a warning when we parse the subclass if the situation is detected and theupcast
info has not been set.Changes in existing presets: addition of
of
in presets with classes having multiple or virtual inheritance (hdf5, opencv, pytorch and tvm)COULD BE IMPROVED:
It would be better if
of
were replaced by a constructor, acting as a specialization of the pointer cast constructor taking aPointer
. This way we limit the risk that the user triggers a segmentation fault by calling the pointer cast constructor when C-style cast won't work. But I don't see how to implement this easily as a constructor, without patching the generator. We could add something like:and make
of
private, but it's not really satisfactory since it just duplicates the object returned byof
. Any idea ?