From 54415f9527dbbb5830fcaa01456ec5cbe952ec69 Mon Sep 17 00:00:00 2001 From: "killua.z" Date: Tue, 5 May 2026 11:57:36 +0400 Subject: [PATCH 1/2] feat: add reference capabilities to positional arguments. use existing v2 api to capture reference arguments. --- src/headers/parser/argument_builder.hpp | 6 +---- src/headers/parser/parser_v2.hpp | 30 ++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/headers/parser/argument_builder.hpp b/src/headers/parser/argument_builder.hpp index 2de870c..26aa89b 100644 --- a/src/headers/parser/argument_builder.hpp +++ b/src/headers/parser/argument_builder.hpp @@ -368,12 +368,8 @@ private: throw std::logic_error("reference() was selected without a target."); } + pairs[argument_parser::v2::flags::Reference] = target; parser.template add_argument(pairs); - parser.on_complete([target, key](argument_parser::base_parser const& completed_parser) { - if (auto value = completed_parser.template get_optional(key)) { - *target = value.value(); - } - }); } auto build_parametered_action(argument_parser::v2::base_parser& parser) const -> void { diff --git a/src/headers/parser/parser_v2.hpp b/src/headers/parser/parser_v2.hpp index bfea633..239ee65 100644 --- a/src/headers/parser/parser_v2.hpp +++ b/src/headers/parser/parser_v2.hpp @@ -154,9 +154,13 @@ namespace argument_parser::v2 { found_params[extended_add_argument_flags::Action] = true; if constexpr (!std::is_same_v) { auto ref = get_or_throw(argument_pairs.at(add_argument_flags::Reference), "reference"); - action = helpers::make_parametered_action([ref](T const& t) { - *ref = t; - }).clone(); + if (action) { + throw std::logic_error("Cannot use both action and reference for the same argument"); + } else { + action = helpers::make_parametered_action([ref](T const& t) { + *ref = t; + }).clone(); + } } else { throw std::logic_error("Reference argument must not be void"); } @@ -255,6 +259,26 @@ namespace argument_parser::v2 { position = get_or_throw(argument_pairs.at(add_argument_flags::Position), "position"); } + if (argument_pairs.find(add_argument_flags::Reference) != argument_pairs.end()) { + if (!IsTyped) { + throw std::logic_error("Reference argument must be typed"); + } + + if constexpr (!std::is_same_v) { + auto ref = get_or_throw(argument_pairs.at(add_argument_flags::Reference), "reference"); + if (action) { + throw std::logic_error("Cannot use both action and reference for the same argument"); + } else { + action = helpers::make_parametered_action([ref](T const& t) { + *ref = t; + }).clone(); + } + } else { + throw std::logic_error("Reference argument must not be void"); + } + } + + if (help_text.empty()) { if constexpr (IsTyped) { if constexpr (internal::sfinae::has_format_hint>::value && From c067bbca38d927140a82afa0223970ad0bc835c9 Mon Sep 17 00:00:00 2001 From: "killua.z" Date: Tue, 5 May 2026 11:58:50 +0400 Subject: [PATCH 2/2] update: example to display capturing capability via positional args. --- examples/test/main.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/examples/test/main.cpp b/examples/test/main.cpp index 09561d1..1cbe83e 100644 --- a/examples/test/main.cpp +++ b/examples/test/main.cpp @@ -52,7 +52,7 @@ auto main() -> int { argument::start() .positional("count") - .position(0) + .position(1) .help_text("How many times to repeat the action.") .action([](int const& count) { std::cout << "count action configured for " << count << '\n'; @@ -66,6 +66,13 @@ auto main() -> int { .reference(captured_value) .build(parser); + argument::start() + .positional("captured") + .position(0) + .help_text("Store the parsed value through a reference.") + .reference(captured_value) + .build(parser); + // parser.add_argument({ // {ShortArgument, "c"}, // {HelpText, "capture count"},