fix: restore the string parameters of split - #22
Merged
Conversation
split took its two arguments as std::string_view. The change was made to express that the function does not own them, and it also happened to work around a build failure on one of the supported compiler and standard library pairings, where the left operand of the views pipe was rejected as a const std::string. The parameter change turned out to cost far more than expected. Nine conversion operators to std::string are declared across the library -- covering seven top-level types, among them path -- and none of them declares a conversion to std::string_view. Passing any of them to split therefore needs two user-defined conversions, which the language does not perform, so the library could no longer pass its own types to its own function. Splitting a PATH on ":" is one of the most typical uses of split, and it stopped compiling. The build failure came from the left operand of the pipe, not from the parameter type. Converting inside the function fixes it while leaving the public signature alone, so restore const std::string& and take a view of each argument in the body. The nine split test cases pass unchanged, and the pairing that failed now builds and runs the suite. The two conversions are not obvious to a reader who has not seen the failure, so a comment records why the pipe is not fed the strings directly. Expressing non-ownership in the parameter type remains the more accurate choice, and the wider question of applying it across the rest of the API is still open. Doing it for split alone is what breaks callers, because the surrounding types are built around std::string; done together, the types and the signatures can be designed to agree.
The public header gained <string_view> when split declared its parameters that way. After restoring const std::string&, nothing in the header names std::string_view -- the only mention left was the include itself -- while src/type.cpp uses it directly and relied on the header to supply it. Move the include to the translation unit that uses the type. <string> stays in the header, since the declarations do name std::string.
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.
What
splittook its two arguments asstd::string_view. This restores them toconst std::string&and converts to views inside the function body instead.Why
The parameter change was made to express that
splitdoes not own itsarguments. It also worked around a build failure on one of the supported
compiler and standard library pairings, where the left operand of the views
pipe was rejected as a
const std::string.The cost turned out to be much larger than it looked. Nine conversion
operators to
std::stringare declared across the library:stringinclude/dross/type/string.h:227numberinclude/dross/type/number.h:249booleaninclude/dross/type/boolean.h:219datainclude/dross/type/data.h:294timezoneinclude/dross/type/timezone.h:135timestampinclude/dross/type/timestamp.h:349timestamp::date_partinclude/dross/type/timestamp.h:144timestamp::time_partinclude/dross/type/timestamp.h:236pathinclude/dross/platform/path.h:222None of them declares a conversion to
std::string_view, so passing any ofthem to
splitneeds two user-defined conversions — which the language doesnot perform. The library could no longer pass its own types to its own
function. Splitting a
PATHon":"is one of the most typical uses ofsplit, and it stopped compiling.Giving those types a
std::string_viewconversion would not have coveredthem.
timezone,timestamp,date_part,time_partandpathall builda fresh string in their conversion operator (
format(),format(format_type::iso8601), anostringstream, andstd::filesystem::path::string()respectively), so they have no stablebuffer to hand out a view over without adding a cache and rules for
invalidating it. Only
stringandnumberhold astd::stringmember.How
The build failure came from the left operand of the pipe, not from the
parameter type — the diagnostic named
const std::stringand the partialsplit adaptor as the operands. Taking a view of each argument inside the
function fixes it without touching the public signature.
A comment records why the pipe is not fed the strings directly, since the
two conversions look redundant to a reader who has not seen the failure.
Verification
The nightly watch was dispatched on this branch, so the pairing that failed
is exercised before merge rather than after.
string_viewinvalid operands to binary expressionsplitconst std::string&occurrences ininclude/+src/The watch job installed the compiler, compiled 32 objects and built the test
target, so the green result is not a skipped job. Locally, all 405 tests pass
under GCC 13 with no warnings, and every listed type compiles as an argument
to
splitunder both GCC 13 and Clang 22.Includes
The public header gained
<string_view>whensplitdeclared itsparameters that way. Nothing in the header names the type any more -- the
include was the only mention left -- while
src/type.cppuses it directlyand relied on the header to supply it. The include moves to the file that
uses it.
<string>stays in the header, since the declarations do namestd::string.Changelog
The entry describing the parameter change is removed rather than amended.
splitpredates theUnreleasedsection and no tag exists, so the netchange against the last released state is nothing.
Not in scope
The rest of the API keeps
const std::string&. Expressing non-ownership inparameter types remains the more accurate choice, and whether to apply it
across the API is still open — but doing it for
splitalone is what brokecallers, because the surrounding types are built around
std::string. Donetogether, the types and the signatures can be designed to agree.