asioexec::completion_token: Conversion From Mutable Lvalue to Rvalue#1725
Merged
ericniebler merged 1 commit intoNVIDIA:mainfrom Dec 31, 2025
Merged
Conversation
Asio operations frequently declare completion signatures which are correct only if you ignore cv- and ref-qualification. That is to say an operation might declare void(int) as its completion signature but in actual fact complete with int& or const int& (rather than the expected int&&). asioexec::completion_token has tried to deal with the above since it was initially added (35a3e31), however this has not been without issue (8bb5b46). The correct way to deal with the above issue (as reified by 8bb5b46) is to use a combination of: - std::is_convertible_v, and - std::reference_converts_from_temporary_v To determine whether values should be forwarded through to the receiver or first converted. Unfortunately compilers/standard libraries that don't feature std::reference_converts_from_temporary_v are supported hence this fallback from 8bb5b46: ( // Just using is_base_of_v is insufficient because it always reports false for built-in types (std::is_base_of_v<std::remove_cvref_t<T>, std::remove_cvref_t<U>> || std::is_same_v<std::remove_cvref_t<T>, std::remove_cvref_t<U>>) && // The returned type must be at least as cv-qualified as the input type (it can be more cv-qualified) at_least_as_qualified_v<std::remove_reference_t<T>, std::remove_reference_t<U>> && ( // Reference type must agree except... (std::is_lvalue_reference_v<T> == std::is_lvalue_reference_v<T>) || // ...special rules for const& which allows rvalues to bind thereto (std::is_lvalue_reference_v<T> && std::is_const_v<std::remove_reference_t<T>>) )) Unfortunately there's a typo under the comment which reads "[r]eference type must agree except:" Both sides of the equality comparison are std:: is_lvalue_reference_v<T> thereby rendering it tautological. This had the effect of activating the overload constrained thereby in the case where: - The destination type (T) is an rvalue reference, and - The source type (U) is a mutable lvalue reference Leading to a compiler error of the following form: error: rvalue reference to type 'boost::system::error_code' cannot bind to lvalue of type 'boost::system::error_code' 100 | return static_cast<U&&>(u); | ^~~~~~~~~~~~~~~~~~~ Which is NVIDIA#1724 (which this commit addresses). Added a reproducing test and fixed.
Collaborator
|
/ok to test b8a2589 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Asio operations frequently declare completion signatures which are correct only if you ignore cv- and ref-qualification. That is to say an operation might declare void(int) as its completion signature but in actual fact complete with int& or const int& (rather than the expected int&&).
asioexec::completion_token has tried to deal with the above since it was initially added (35a3e31), however this has not been without issue (8bb5b46).
The correct way to deal with the above issue (as reified by 8bb5b46) is to use a combination of:
To determine whether values should be forwarded through to the receiver or first converted. Unfortunately compilers/standard libraries that don't feature std::reference_converts_from_temporary_v are supported hence this fallback from 8bb5b46:
Unfortunately there's a typo under the comment which reads "[r]eference type must agree except:" Both sides of the equality comparison are std:: is_lvalue_reference_v thereby rendering it tautological. This had the effect of activating the overload constrained thereby in the case where:
Leading to a compiler error of the following form:
Which is #1724 (which this commit addresses).
Added a reproducing test and fixed.