Skip to content

Make store_into() respect a preceding scan() format - #434

Open
afonsojanu wants to merge 1 commit into
p-ranav:masterfrom
afonsojanu:fix/store-into-respects-scan-format
Open

Make store_into() respect a preceding scan() format#434
afonsojanu wants to merge 1 commit into
p-ranav:masterfrom
afonsojanu:fix/store-into-respects-scan-format

Conversation

@afonsojanu

Copy link
Copy Markdown

Closes #415.

store_into() for integral and floating-point types always parses the raw argument itself, hardcoded to base-10 (or a general float format). That's fine on its own, but if scan() was called first to pick a different format, the two collide:

uint64_t foo;
program.add_argument("foo").scan<'x', uint64_t>().store_into(foo);
program.parse_args({"prog", "0xABCD"});

This throws std::invalid_argument, because store_into's own action tries to read "0xABCD" as a decimal number, ignoring that scan<'x', ...> already parsed it correctly as hex. program.get<uint64_t>() actually returns the right value in this scenario since it just reads the first parsed result, so the mismatch was specific to store_into.

The fix: when another action (like scan()) already ran before store_into and produced a value of the target type, reuse that value instead of re-parsing the string with a hardcoded format. If there's no such value available (e.g. a side-effect-only custom action ran first, which is exercised by an existing test in this file), it falls back to parsing the raw string itself exactly like before, so nothing about the existing single-action behavior changes.

Added two regression tests covering scan<'x', uint64_t>().store_into(...) and scan<'g', double>().store_into(...). Ran the full suite locally (247 cases, 899 assertions) before and after - all green, including the existing test that mixes a custom action with store_into, which is what caught the edge case where the earlier action doesn't produce a reusable value.

store_into() for integral and floating-point types always re-parsed the
raw argument as base-10 (or general float), even when scan() had already
been called on the same argument to configure a different format like
hex. That meant something like

  program.add_argument("foo").scan<'x', uint64_t>().store_into(foo);

would throw std::invalid_argument on any hex input, since store_into's
own action tried to read it as decimal.

Now, if an earlier action already produced a value of the right type,
store_into just reuses it. If not (e.g. a side-effect-only custom
action ran first), it falls back to the old behavior of parsing the
raw string itself, so existing usages keep working the same way.

Fixes p-ranav#415.
@wanjiadenghuo111

wanjiadenghuo111 commented Sep 6, 2026 via email

Copy link
Copy Markdown

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.

store_into does not properly handle numeric types

2 participants