Add a reference constructor to Span
. Replace VectorView
with Span
#106389
+286
−305
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Span
, creating aSpan
of length 1. #103931This PR adds an implicit conversion from any value reference to a single-element
Span
, matching a constructorVectorView
already had.With this addition,
VectorView
can finally be merged intoSpan
.Span from reference
I finally found a way to satisfyingly support single reference constructors for
Span
!My initial implementation was the same as
VectorView
, implemented in #103931. However, I was not happy with it because it meant thatSpan
could be implicitly created from any value, which made me very uneasy.Still, after having thought about it for a while, it does make sense for a value to be passed into a function that expects a
Span
: It just means we want to run the function on the one value. For example, in the future the function could be overloaded with a single value version, automatically optimizing all callers that were previously implicitly converting toSpan
.An insight came in the form of implicit type checks. Consider the following code example:
This compiles fine, but will crash horribly if
span2
is ever used, becausei
is implicitly converted todouble
, but the temporary is dropped after the call, making theSpan
immediately garbage.However, using the following implementation (used in this PR) makes this much safer:
Using this constructor instead,
Span<double> span2(i)
will statically fail because implicit conversions are not allowed for this constructor.VectorView to Span
VectorView
was initially intended to be used widely across the codebase:godot/servers/rendering/rendering_device_driver.h
Lines 55 to 56 in 09fcbb8
Span
is this implementation. With the reference constructor out of the way, the two can finally be merged. All that was required was a search-and-replace fromVectorView
toSpan
.Notably, the use of SFINAE requires explicit conversions:
In this case it would probably be better to just accept implicit conversions. But I do feel safer with these checks, and we can always generalize if this becomes a problem.
Dangers
Converting from a reference to
Span
can be considered dangerous. Consider the following code:This will obviously go horribly wrong.
However, this problem already exists in C++ plain:
This compiles fine, but will also go horribly wrong.
The main difference is that the compiler will (usually) warn about the latter implementation, but may not understand
Span
well enough to also warn about the former implementation.All in all, I think this risk is acceptable, considering C++ is full of memory pitfalls, and this isn't any worse than what C++ has in store for us in other places.