-
Notifications
You must be signed in to change notification settings - Fork 38.7k
Support serialization as another type without casting #12712
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
Conversation
With the new AsType function it's possible to serialize an object as another (compatible) type, and is intended for invoking the serializer of a parent class. Writing AsType<Parent>(child) will work in any context: * READWRITE(AsType<Parent>(child)) * s << AsType<Parent>(child) * s >> AsType<Parent>(child) In case child is const, the result will be a reference to a const Parent type, resulting in const-correct behavior.
|
utACK a6e5ddc |
|
utACK a6e5ddc |
|
utACK a6e5ddc |
|
-0 This adds a new codebase specific function for which a perfectly adequate language-standard one exists. It's just one more thing for people new to the codebase to see and ask themselves "but why not static_cast"? Converting the invocations from |
|
@jimpo That doesn't work when the constness of the argument isn't known. I guess the context isn't entirely clear in this PR, but the goal is to have serialization functions that use single implementation that taken a const argument when serializing and non-const argument when deserializing. Simple static casts aren't enough, as they don't maintain constness, but I'd be happy to learn about another approach. EDIT: I've added a rationale to the PR description; you're very right to point out it wasn't sufficient. |
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.
utACK a6e5ddc, with caveat that I think @jimpo makes a good point about downsides of adding a new cast. IMO, it would be clearer to drop AsType and replace:
READWRITE(AsType<Parent>(child))s << AsType<Parent>(child)s >> AsType<Parent>(child)
with:
READWRITEAS(child, Parent)s << static_cast<const Parent&>(child)s >> static_cast<Parent&>(child)
I don't think AsType actually serves a useful function except when it's being used in combination with the READWRITE macro, and in that case, it could just be built in to the macro. In other contexts, AsType could even be dangerous since it potentially returns references to temporaries.
|
@ryanofsky I was trying to avoid as much macro magic as possible.
Can you give an example? |
To be clear, I'm not suggesting replacing I don't think macro magic calls like
const Base& i = CastAs<Base>(Derived());It just seems like the |
Sure, but that has nothing to do with the
Or even:
|
That's a good point. I can see how it is a benefit of the current approach. I'm not sure it actually justifies exposing the cast construct, but makes sense.
This is safe due to reference lifetime extension (https://abseil.io/tips/107). My example wasn't safe because lifetime extension can't work in that case. To be sure, I don't actually think this is a big deal. It's just a general reason to be wary of functions like |
Right, I guess that's the question. After the discussion above with @jimpo and @ryanofsky I'm fine with either the |
|
Can't speak for @jimpo. I prefer |
|
I also prefer |
|
Thanks, good points. I'll redo this. |
818dc74 Support serialization as another type without casting (Pieter Wuille) Pull request description: This adds a `READWRITEAS(type, obj)` macro which serializes `obj` as if it were converted to `const type&` when `const`, and to `type&` when non-`const`. No actual cast is involved, so this only works when this conversion can be done automatically. This makes it usable in serialization code that uses a single implementation for both serialization and deserializing, which doesn't know the constness of the object involved. This is a redo of #12712, using a slightly different interface. Tree-SHA512: 262f0257284ff99b5ffaec9b997c194e221522ba35c3ac8eaa9bb344449d7ea0a314de254dc77449fa7aaa600f8cd9a24da65aade8c1ec6aa80c6e9a7bba5ca7
…sting 818dc74 Support serialization as another type without casting (Pieter Wuille) Pull request description: This adds a `READWRITEAS(type, obj)` macro which serializes `obj` as if it were converted to `const type&` when `const`, and to `type&` when non-`const`. No actual cast is involved, so this only works when this conversion can be done automatically. This makes it usable in serialization code that uses a single implementation for both serialization and deserializing, which doesn't know the constness of the object involved. This is a redo of bitcoin#12712, using a slightly different interface. Tree-SHA512: 262f0257284ff99b5ffaec9b997c194e221522ba35c3ac8eaa9bb344449d7ea0a314de254dc77449fa7aaa600f8cd9a24da65aade8c1ec6aa80c6e9a7bba5ca7
With the new
AsTypefunction it's possible to serialize an object as another (compatible) type, and is intended for invoking the serializer of a parent class.Writing
AsType<Parent>(child)will work in any context:READWRITE(AsType<Parent>(child))s << AsType<Parent>(child)s >> AsType<Parent>(child)In case child is
const, the result will be a reference to aconst Parenttype, resulting in const-correct behavior.For now this primitive isn't very useful, as the constness is statically known in each of the instances (so a simple cast would work). However, in #10785 I plan to modify the serialization code to have a single implementation which works on a const object when serializing and non-const when deserializing.
AsTypebehaves correctly in this case, maintaining the constness of the argument. It's also safer, as this only involves automatic type conversions, and no explicit casts.