Skip to content

fix: restore the string parameters of split - #22

Merged
skipbit merged 2 commits into
mainfrom
fix/restore-split-string-parameters
Aug 11, 2026
Merged

fix: restore the string parameters of split#22
skipbit merged 2 commits into
mainfrom
fix/restore-split-string-parameters

Conversation

@skipbit

@skipbit skipbit commented Aug 11, 2026

Copy link
Copy Markdown
Owner

What

split took its two arguments as std::string_view. This restores them to
const std::string& and converts to views inside the function body instead.

Why

The parameter change was made to express that split does not own its
arguments. 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::string are declared across the library:

Type Declared at
string include/dross/type/string.h:227
number include/dross/type/number.h:249
boolean include/dross/type/boolean.h:219
data include/dross/type/data.h:294
timezone include/dross/type/timezone.h:135
timestamp include/dross/type/timestamp.h:349
timestamp::date_part include/dross/type/timestamp.h:144
timestamp::time_part include/dross/type/timestamp.h:236
path include/dross/platform/path.h:222

None of them declares a conversion to std::string_view, so passing any of
them to split needs two user-defined conversions — which the language does
not perform. 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.

Giving those types a std::string_view conversion would not have covered
them. timezone, timestamp, date_part, time_part and path all build
a fresh string in their conversion operator (format(),
format(format_type::iso8601), an ostringstream, and
std::filesystem::path::string() respectively), so they have no stable
buffer to hand out a view over without adding a cache and rules for
invalidating it. Only string and number hold a std::string member.

How

The build failure came from the left operand of the pipe, not from the
parameter type — the diagnostic named const std::string and the partial
split adaptor as the operands. Taking a view of each argument inside the
function fixes it without touching the public signature.

const std::string_view sv{s};
const std::string_view dv{delimiter};
auto range = sv | std::views::split(dv) | ...

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.

Before the parameter change With string_view This branch
invalid operands to binary expression present gone gone
Build under the watched compiler stopped succeeded succeeded
Test suite not reached 405 passed 405 passed
Library types accepted by split all none all
const std::string& occurrences in include/ + src/ 82 80 82

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 split under both GCC 13 and Clang 22.

Includes

The public header gained <string_view> when split declared its
parameters that way. Nothing in the header names the type any more -- the
include was the only mention left -- while src/type.cpp uses it directly
and 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 name
std::string.

Changelog

The entry describing the parameter change is removed rather than amended.
split predates the Unreleased section and no tag exists, so the net
change against the last released state is nothing.

Not in scope

The rest of the API keeps const std::string&. Expressing non-ownership in
parameter types remains the more accurate choice, and whether to apply it
across the API is still open — but doing it for split alone is what broke
callers, because the surrounding types are built around std::string. Done
together, the types and the signatures can be designed to agree.

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.
@skipbit
skipbit merged commit da8e1f1 into main Aug 11, 2026
27 checks passed
@skipbit
skipbit deleted the fix/restore-split-string-parameters branch August 11, 2026 12:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant