Files
argument-parser/DOCS.MD
2026-05-13 14:17:25 +04:00

31 KiB

Argument Parser API Documentation

This document covers the public API exposed by:

  • src/headers/parser/argument_parser.hpp: the original v1 parser surface.
  • src/headers/parser/parser_v2.hpp: the v2 map/initializer-list facade.
  • src/headers/parser/argument_builder.hpp: the staged fluent builder for v2.

The lower-level v1 API still powers the platform parsers and v2. New code will usually be clearest with argument_parser::v2 and argument_parser::builder::new_argument(), but the v1 types remain public and useful when you need direct control over actions, stored values, or positional registration.

Common Concepts

Argument names are registered without command-line prefixes. Use "v" and "verbose", not "-v" or "--verbose". The active convention objects decide which concrete syntaxes are accepted during parsing and how help text is rendered.

Typed values are parsed through argument_parser::parsing_traits::parser_trait<T>::parse(std::string const&). The built-in traits cover common scalar types such as std::string, bool, int, float, and double; custom value types need a trait specialization. Trait format_hint and purpose_hint members are used in help text and parse error messages when available.

Stored values are type-erased internally. Retrieve them with the same type used when the argument was registered.

v1 API: argument_parser.hpp

The public v1 types live in the argument_parser namespace unless otherwise noted.

action_base

class action_base {
public:
    virtual ~action_base() = default;
    [[nodiscard]] virtual bool expects_parameter() const = 0;
    virtual void invoke() const = 0;
    virtual void invoke_with_parameter(std::string const& param) const = 0;
    [[nodiscard]] virtual std::pair<std::string, std::string> get_trait_hints() const = 0;
    [[nodiscard]] virtual std::unique_ptr<action_base> clone() const = 0;
};

action_base is the polymorphic interface stored by registered arguments. Application code normally uses action_with_param<T>, action_no_param, or the overloaded helpers::make_action(...) factories instead of implementing this interface directly.

  • expects_parameter() reports whether the action consumes a value token.
  • invoke() runs a no-value action. On action_with_param<T>, it throws std::runtime_error.
  • invoke_with_parameter(param) runs a value action. On action_no_param, the parameter is ignored.
  • get_trait_hints() returns {format_hint, purpose_hint} for typed actions when the parser trait exposes those members.
  • clone() returns a heap-allocated copy used by argument.

action_with_param<T>

template <typename T>
class action_with_param : public action_base {
public:
    using parameter_type = T;

    explicit action_with_param(std::function<void(T const&)> const& handler);
    void invoke(T const& arg) const;
    [[nodiscard]] bool expects_parameter() const override;
    void invoke() const override;
    void invoke_with_parameter(std::string const& param) const override;
    [[nodiscard]] std::pair<std::string, std::string> get_trait_hints() const override;
    [[nodiscard]] std::unique_ptr<action_base> clone() const override;
};

Adapts a std::function<void(T const&)> into a parser action. During invoke_with_parameter, the raw string is converted with parser_trait<T>::parse(param) and the parsed value is passed to the handler. Parse failures are reported as std::runtime_error with trait-derived hints when available.

action_no_param

class action_no_param : public action_base {
public:
    explicit action_no_param(std::function<void()> const& handler);

    void invoke() const override;
    [[nodiscard]] bool expects_parameter() const override;
    void invoke_with_parameter(std::string const& param) const override;
    [[nodiscard]] std::pair<std::string, std::string> get_trait_hints() const override;
    [[nodiscard]] std::unique_ptr<action_base> clone() const override;
};

Adapts a std::function<void()> into a flag-style action. expects_parameter() returns false; invoke_with_parameter(...) ignores the parameter and runs the no-value handler.

argument_parser::helpers

namespace argument_parser::helpers {
    template <typename T>
    action_with_param<T>
    make_action(std::function<void(T const&)> const& function);

    action_no_param
    make_action(std::function<void()> const& function);
}

Factory helpers for creating action objects used by base_parser and v2.

parser_settings

struct parser_settings {
    bool should_exit_on_error = true;
    bool should_exit_on_missing_required = true;
    bool should_exit_on_unknown_argument = true;
    bool should_exit_on_help = true;

    bool ignore_unknown_arguments = false;
    bool ignore_errors = false;
};

constexpr static inline parser_settings no_exit{
    false,
    false,
    false,
    false
};

parser_settings configures how the parser reacts to help, parse errors, unknown arguments, and missing required arguments. The default settings preserve CLI-style behavior: help exits after printing, unknown arguments and parse errors exit with status 1, and missing required arguments print diagnostics and help before exiting.

Use argument_parser::no_exit when embedding the parser in tests, tools, or larger applications that should receive exceptions instead of process exits:

argument_parser::v2::parser parser(argument_parser::no_exit);

For targeted behavior, pass an explicit settings object to the v2 platform parser constructor:

argument_parser::parser_settings settings;
settings.should_exit_on_help = false;
settings.should_exit_on_error = false;
settings.should_exit_on_unknown_argument = false;
settings.should_exit_on_missing_required = false;
settings.ignore_unknown_arguments = true;

argument_parser::v2::parser parser(settings);

The fields have these effects:

  • should_exit_on_help: controls whether the automatically registered v2 -h / --help action calls std::exit(0) after printing help.
  • should_exit_on_error: when true, non-unknown parse errors caught by handle_arguments(...) call std::exit(1); when false, the exception is rethrown.
  • should_exit_on_unknown_argument: when true, unknown arguments caught by handle_arguments(...) call std::exit(1); when false, the unknown argument exception is rethrown.
  • should_exit_on_missing_required: when true, missing required arguments print diagnostics/help and call std::exit(1); when false, they throw std::runtime_error.
  • ignore_unknown_arguments: when true, tokens that match no convention and cannot be consumed as positionals are skipped.
  • ignore_errors: reserved in the public settings struct in the current worktree; no runtime branch currently reads it.

argument

class argument {
public:
    argument();

    template <typename ActionType>
    argument(int id, std::string name, ActionType const& action);

    argument(argument const& other);
    argument& operator=(argument const& other);
    argument(argument&& other) noexcept = default;
    argument& operator=(argument&& other) noexcept = default;

    [[nodiscard]] bool is_required() const;
    [[nodiscard]] std::string get_name() const;
    [[nodiscard]] bool is_invoked() const;
    [[nodiscard]] bool expects_parameter() const;
    [[nodiscard]] std::string get_help_text() const;
    [[nodiscard]] bool is_positional() const;
    [[nodiscard]] bool is_positional_accumulator() const;
    [[nodiscard]] std::optional<int> get_position_index() const;
};

argument is the public descriptor returned by parser lookup operations. It is copyable; copies clone their stored action.

  • is_required() reports whether parsing must see this argument.
  • get_name() returns the registered display name. Named options are stored as "<short>|<long>"; positional arguments use their positional name.
  • is_invoked() reports whether the action ran during handle_arguments(...).
  • expects_parameter() mirrors the stored action.
  • get_help_text() returns the registration help text.
  • is_positional() identifies positional arguments.
  • is_positional_accumulator() is true for positional accumulators.
  • get_position_index() returns the explicit requested position, or std::nullopt.

base_parser

class base_parser {
public:
    template <typename T>
    void add_argument(
        std::string const& short_arg,
        std::string const& long_arg,
        std::string const& help_text,
        action_with_param<T> const& action,
        bool required);

    template <typename T>
    void add_argument(
        std::string const& short_arg,
        std::string const& long_arg,
        std::string const& help_text,
        bool required);

    void add_argument(
        std::string const& short_arg,
        std::string const& long_arg,
        std::string const& help_text,
        action_no_param const& action,
        bool required);

    void add_argument(
        std::string const& short_arg,
        std::string const& long_arg,
        std::string const& help_text,
        bool required);

    template <typename T>
    void add_positional_argument(
        std::string const& name,
        std::string const& help_text,
        action_with_param<T> const& action,
        bool required,
        std::optional<int> position = std::nullopt);

    template <typename T>
    void add_positional_argument(
        std::string const& name,
        std::string const& help_text,
        bool required,
        std::optional<int> position = std::nullopt);

    template <typename T>
    void add_positional_accumulator(
        std::string const& name,
        std::string const& help_text,
        action_with_param<T> const& action,
        bool required,
        std::optional<int> position = std::nullopt);

    void on_complete(std::function<void(base_parser const&)> const& action);

    template <typename T>
    std::optional<T> get_optional(std::string const& arg) const;

    [[nodiscard]] std::string build_help_text(
        std::initializer_list<conventions::convention const* const> convention_types) const;

    argument& get_argument(conventions::parsed_argument const& arg);
    [[nodiscard]] std::optional<int> find_argument_id(std::string const& arg) const;
    void handle_arguments(
        std::initializer_list<conventions::convention const* const> convention_types);
    void display_help(
        std::initializer_list<conventions::convention const* const> convention_types) const;

protected:
    base_parser() = default;
};

base_parser owns registrations, parsed command-line tokens, stored values, required-argument checks, and completion hooks. Its constructor is protected; users normally instantiate a concrete parser from <argparse> or a platform header. Platform parser constructors populate program_name and parsed_arguments from the native process arguments.

base_parser is not thread-safe. handle_arguments(...) must be called on the same thread that created the parser or it throws std::runtime_error.

Named Arguments

Use add_argument(...) for short and/or long options. The v1 API uses "-" as the sentinel for an omitted short or long name.

argument_parser::parser parser;

parser.add_argument<std::string>(
    "o",
    "output",
    "Output file.",
    argument_parser::helpers::make_action<std::string>(
        [](std::string const& value) {
            // use value
        }),
    true);

parser.add_argument(
    "v",
    "verbose",
    "Enable verbose output.",
    false);

Registration fails with std::runtime_error("The key already exists!") if the short or long key is already registered. Because duplicate checks also see the "-" sentinel, avoid registering multiple v1 arguments that pass "-" for the same side unless you have verified that behavior.

The overloads behave as follows:

  • add_argument<T>(..., action_with_param<T> const& action, bool required) parses a value and invokes the supplied typed action.
  • add_argument<T>(..., bool required) parses a value and stores it internally for get_optional<T>(...).
  • add_argument(..., action_no_param const& action, bool required) invokes a no-value action.
  • add_argument(..., bool required) stores true internally when the option is present.

Positional Arguments

parser.add_positional_argument<std::string>(
    "input",
    "Input path.",
    true,
    0);

parser.add_positional_argument<int>(
    "count",
    "Number of iterations.",
    argument_parser::helpers::make_action<int>(
        [](int value) {
            // use value
        }),
    false);

Positional arguments are matched against tokens that do not match any supplied convention. You can provide an explicit zero-based position, or omit it to use the next available positional slot.

add_positional_argument<T>(..., bool required, ...) stores the parsed value internally under the positional name. The action overload invokes the supplied typed action.

add_positional_accumulator<T>(...) registers a typed positional action that can consume repeated positional tokens at its slot. Only one positional accumulator is allowed, and it must be the last positional argument. Duplicate names, negative explicit positions, or invalid accumulator placement throw std::runtime_error.

Parsing

parser.handle_arguments({
    &argument_parser::conventions::gnu_argument_convention,
    &argument_parser::conventions::gnu_equal_argument_convention,
    &argument_parser::conventions::windows_argument_convention,
    &argument_parser::conventions::windows_equal_argument_convention,
});

handle_arguments(...) invokes matching actions, records stored values, checks required arguments, then runs completion hooks. For each token, conventions are tried in order. If no convention matches, the token is consumed as the next positional value when one is available. -- forces all following tokens to be treated as positional values.

Unknown options, missing values, parse failures, unexpected positional values, and action errors are reported with std::runtime_error. Missing required arguments print diagnostics and help text, then call std::exit(1).

If a registered argument named h or help is found, the parser invokes that help argument and returns from argument invocation early. Required checks and completion hooks still run after invocation returns.

Lookup And Help

if (auto output = parser.get_optional<std::string>("output")) {
    // *output is the stored value
}

auto id = parser.find_argument_id("output");
std::string help = parser.build_help_text({
    &argument_parser::conventions::gnu_argument_convention,
});
parser.display_help({
    &argument_parser::conventions::gnu_argument_convention,
});

get_optional<T>(arg) returns a stored value for a registered short name, long name, or positional name. It returns std::nullopt when no argument by that name exists or when no value was stored. If a value exists but T does not match the stored type, std::any_cast<T> throws std::bad_any_cast.

find_argument_id(arg) returns the internal integer id for a registered short name, long name, or positional name. get_argument(parsed_argument) resolves a parsed convention result to an argument& and throws when no match exists.

build_help_text(...) returns formatted usage text. display_help(...) writes that text to std::cout.

Completion Hooks

parser.on_complete([](argument_parser::base_parser const& state) {
    // inspect state.get_optional<T>(...)
});

on_complete(...) appends a callback that runs after successful argument invocation and required-argument checks.

v2 API: parser_v2.hpp

The v2 API is declared under argument_parser::v2. It provides a map/initializer-list facade over the v1 base_parser, while still accepting the same convention objects and action helpers.

Typical use is through the platform alias from <argparse>:

#include <argparse>

using namespace argument_parser::v2::flags;

int main() {
    argument_parser::v2::parser parser(argument_parser::no_exit);

    parser.add_argument<int>({
        {LongArgument, "count"},
        {HelpText, "Number of items to process."},
        {Required, true},
    });

    parser.handle_arguments({
        &argument_parser::conventions::gnu_argument_convention,
        &argument_parser::conventions::windows_argument_convention,
    });

    auto count = parser.get_optional<int>("count");
}

enum class add_argument_flags

These keys describe an argument passed to v2::base_parser::add_argument.

Flag Value type Meaning
ShortArgument std::string Short option name, such as "v".
LongArgument std::string Long option name, such as "verbose".
Positional std::string Registers a positional argument. When present, the positional registration path is used.
Position int Optional zero-based position for a positional argument.
HelpText std::string Help text shown in generated help output.
Action action_with_param<T> or action_no_param Callback invoked when the argument is found.
Required bool Marks the argument required when true.
Reference T* Stores a parsed typed value into an external object. Cannot be combined with Action.
Accumulate bool or T* Repeated-value mode. For std::vector<U>, each parsed U is appended. For int, each occurrence increments the count.

The argument_parser::v2::flags namespace exposes inline constants with the same names for concise initializer-list calls.

using namespace argument_parser::v2::flags;

parser.add_argument({
    {ShortArgument, "q"},
    {HelpText, "Quiet mode."},
});

argument_parser::v2::deducers

template <typename, typename = void>
struct has_value_type;

template <typename T>
struct is_vector;

template <typename T>
constexpr bool is_vector_v = is_vector<T>::test();

These public type traits are used by v2 accumulator logic. has_value_type detects T::value_type. is_vector<T>::test() and is_vector_v<T> are true only when T is exactly a std::vector specialization.

argument_parser::v2::base_parser

v2::base_parser is the v2 facade. Concrete platform parsers such as argument_parser::v2::linux_parser, macos_parser, windows_parser, and the portable <argparse> alias argument_parser::v2::parser derive from it. The v2 platform parser constructors accept parser_settings const& settings = {}. Use the default constructor for normal command-line tools, or pass argument_parser::no_exit / a custom parser_settings object when the caller should handle errors without automatic process exits.

The class privately inherits from the v1 argument_parser::base_parser and re-exposes selected operations.

template <typename T>
using typed_flag_value =
    std::variant<std::string, action_with_param<T>, bool, int, T*>;

using non_typed_flag_value =
    std::variant<std::string, action_no_param, bool, int>;

template <typename T>
using typed_argument_pair =
    std::pair<add_argument_flags, typed_flag_value<T>>;

using non_typed_argument_pair =
    std::pair<add_argument_flags, non_typed_flag_value>;

Use typed aliases for arguments that parse a value of T, run an action_with_param<T>, store into a T, or accumulate values. Use non-typed aliases for boolean flags and no-parameter actions.

Typed add_argument

template <typename T>
void add_argument(
    std::unordered_map<add_argument_flags, typed_flag_value<T>> const& argument_pairs);

template <typename T>
void add_argument(std::initializer_list<typed_argument_pair<T>> const& pairs);

Registers a typed option or positional argument. For non-positional options, provide at least one of ShortArgument or LongArgument. If only one name is supplied, the other is internally set to "-" and not registered.

Without Action, Reference, or Accumulate, the parsed T is stored internally and can be read with get_optional<T>(). For positional arguments, include Positional; Position can place the argument at a specific zero-based slot.

int threshold = 0;

parser.add_argument<int>({
    {LongArgument, "threshold"},
    {Reference, &threshold},
    {HelpText, "Store the parsed threshold."},
});

Non-Typed add_argument

void add_argument(
    std::unordered_map<add_argument_flags, non_typed_flag_value> const& argument_pairs);

void add_argument(std::initializer_list<non_typed_argument_pair> const& pairs);

Registers a non-typed option or positional argument. For options, provide at least one of ShortArgument or LongArgument. Without Action, the argument behaves as a boolean flag: when present, it stores true for get_optional<bool>().

With Action, provide an action_no_param. Non-typed arguments cannot use Reference or Accumulate. A non-typed positional argument is stored as std::string.

parser.add_argument({
    {ShortArgument, "v"},
    {LongArgument, "verbose"},
    {HelpText, "Enable verbose output."},
});

Other Public Operations

argument_parser::base_parser& to_v1();

void handle_arguments(
    std::initializer_list<conventions::convention const* const> convention_types);

template <typename T>
std::optional<T> get_optional(std::string const& arg);

using argument_parser::base_parser::display_help;
using argument_parser::base_parser::on_complete;

to_v1() returns a mutable reference to the underlying v1 parser interface. handle_arguments(...), get_optional<T>(...), display_help(...), and on_complete(...) follow the v1 behavior described above.

Accumulation

Accumulate has special typed behavior:

  • T = std::vector<U> registers an argument that accepts repeated U values.
  • T = int registers a counter-style option; each occurrence increments the count.
  • Accumulate set to true stores the accumulated result internally and makes it available through get_optional<T>().
  • Accumulate set to T*, or Accumulate combined with Reference, writes directly to an external object.

For vector accumulators, the public argument type is std::vector<U>, but each individual command-line occurrence is parsed as U.

parser.add_argument<std::vector<int>>({
    {LongArgument, "include-id"},
    {Accumulate, true},
    {HelpText, "May be repeated."},
});

auto ids = parser.get_optional<std::vector<int>>("include-id");

Builder API: argument_builder.hpp

The public builder API lives under argument_parser::builder. It provides a staged fluent interface for registering arguments with argument_parser::v2::base_parser.

#include <argument_builder.hpp>
// or
#include <argparse>

using argument_parser::builder::new_argument;

Public Types

non_type is a marker type used before a value-producing mode has been selected. Application code normally does not need to name it.

builder_mask is a public namespace containing the compile-time machinery used by argument<mask, store_type>. It exposes mask_type, value_mode, extra_capability, capability constants such as short_argument, long_argument, positional, help_text, required, reference, accumulate, count, store, and flag, plus constexpr helpers such as bit, has, remove, replace, is_buildable, and is_build_and_gettable. These are mainly useful for type-level tests or advanced wrappers.

container<store_type>

template <typename store_type>
class container;

Returned by build_and_get(parser). It is populated after parser.handle_arguments(...) completes.

  • store_type get() const returns the stored value. Call only after the container is populated.
  • store_type& operator*() dereferences the stored value.
  • store_type* operator->() accesses members of the stored value.
  • operator bool() reports whether a value is available.

For builder-managed storage, build_and_get() registers an on_complete callback that reads the parsed value by lookup key. For accumulate(existing_vector), the container references the provided vector directly.

argument<mask, store_type>

template <
    argument_parser::builder::builder_mask::mask_type mask =
        argument_parser::builder::builder_mask::initial,
    typename store_type = argument_parser::builder::non_type>
class argument;

The staged fluent builder. mask enables only valid next methods at compile time. store_type is the type produced by the selected value mode. Most users should create builders with new_argument().

Entry Points

static auto argument<>::start() -> argument<builder_mask::initial>;
static inline auto new_argument();

new_argument() is equivalent to argument<>::start().

new_argument()
    .long_argument("output")
    .store<std::string>()
    .required()
    .build(parser);

Identifier Methods

At least one identifier method must be used before build(parser) or build_and_get(parser).

auto short_argument(std::string short_name) const -> argument<..., store_type>;
auto long_argument(std::string long_name) const -> argument<..., store_type>;
auto positional(std::string positional_name) const -> argument<..., store_type>;
auto position(int index) const -> argument<..., store_type>;

short_argument(...) and long_argument(...) set named option identifiers and can be combined with each other. positional(...) registers a positional argument and is mutually exclusive with named identifiers. position(...) is available only after positional(...) and only once. If no value mode is selected for a positional argument, build(parser) registers a std::string positional value.

Metadata Methods

auto help_text(std::string help) const -> argument<..., store_type>;
auto required(bool value = true) const -> argument<..., store_type>;

help_text(...) sets generated help text and is single-use. If omitted, v2 generates default text, often using parser trait hints for typed value modes.

required(...) marks the argument required when value is true. There is no public setRequired(...) method in argument_builder.hpp; the public fluent API is required(...).

Terminal Value Modes

Exactly one terminal value mode can be selected. Once selected, the other modes are removed from the builder type.

template <typename T = std::string>
auto store() const -> argument<..., T>;

template <typename T>
auto reference(T& value) const -> argument<..., T>;

auto flag() const -> argument<..., bool>;

template <typename T = std::string>
auto accumulate() const -> argument<..., std::vector<T>>;

template <typename T>
auto accumulate(T& value) const -> argument<..., T>;

auto count() const -> argument<..., int>;
auto count(int& value) const -> argument<..., int>;

template <typename Callable>
auto action(Callable&& handler) const -> argument<..., non_type>;

template <typename T = std::string, typename Callable>
auto action(Callable&& handler) const -> argument<..., T>;

store<T>() parses a value and stores it in the parser for later lookup. store<void>() is rejected at compile time.

reference(T&) parses a value and assigns it directly to an object that must outlive parsing.

flag() registers a boolean presence flag. It is not available for positional arguments. Named arguments also default to flag behavior when no terminal mode is selected.

accumulate<T>() accepts repeated values and stores them as std::vector<T>. accumulate(existing) appends repeated values into an existing vector. The existing object must be a std::vector and must outlive parsing.

count() counts how many times a named argument appears. count(int&) writes the count into an existing integer. count() is not available for positional arguments.

action(handler) registers a no-value action when handler is invocable as void(). For positional arguments, the builder adapts it through a std::string positional action and ignores the parsed positional text.

action<T>(handler) registers a typed action when handler is invocable as void(T const&). action<void>(...) is rejected at compile time.

Build Methods

auto build(argument_parser::v2::base_parser& parser) const -> void;

auto build_and_get(argument_parser::v2::base_parser& parser) const
    -> container<store_type>;

build(parser) registers the configured argument with the parser. It requires an identifier, dispatches to the selected terminal mode, and defaults to a named boolean flag or std::string positional value when no terminal mode was selected. It may propagate validation errors from v2::base_parser.

build_and_get(parser) registers the argument and returns a container<store_type> for storable modes such as store<T>(), flag(), default named flags, accumulate<T>(), accumulate(vector&), count(), and count(int&). It throws std::logic_error for unsupported terminal modes such as actions. The returned container is normally empty until parser.handle_arguments(...) completes.

Compile-Time Builder Rules

Invalid fluent chains fail to compile rather than failing at runtime.

  • build(...) requires short_argument(...), long_argument(...), or positional(...).
  • short_argument(...) and long_argument(...) can be combined.
  • positional(...) is mutually exclusive with named identifiers.
  • position(...) is available only after positional(...) and only once.
  • help_text(...) and required(...) are single-use.
  • Terminal value modes are mutually exclusive.
  • flag() and count() are not available for positional arguments.
  • store<void>() and action<void>(...) are rejected with static_assert.
  • accumulate(existing) requires existing to be a std::vector.

The header also exposes argument_parser::builder::assertions, a namespace of small compile-time detection helpers and static_assert checks used to verify these staged-builder rules. They are not needed for normal parser configuration.

Complete Builder Example

#include <argparse>
#include <iostream>
#include <string>
#include <vector>

using argument_parser::builder::new_argument;

int main() {
    argument_parser::v2::parser parser(argument_parser::no_exit);

    int threshold = 0;
    std::vector<int> ids;

    new_argument()
        .long_argument("file")
        .store<std::string>()
        .required()
        .help_text("Input file.")
        .build(parser);

    new_argument()
        .long_argument("threshold")
        .reference(threshold)
        .build(parser);

    new_argument()
        .long_argument("id")
        .accumulate(ids)
        .help_text("Repeatable numeric id.")
        .build(parser);

    auto verbose = new_argument()
        .short_argument("v")
        .count()
        .build_and_get(parser);

    parser.handle_arguments({
        &argument_parser::conventions::gnu_argument_convention,
        &argument_parser::conventions::windows_argument_convention,
    });

    if (auto file = parser.get_optional<std::string>("file")) {
        std::cout << "file: " << *file << '\n';
    }

    if (verbose) {
        std::cout << "verbosity: " << *verbose << '\n';
    }

    std::cout << "threshold: " << threshold << '\n';
    std::cout << "ids: " << ids.size() << '\n';
}

Caveats

  • The v1 API is retained as public compatibility surface, but the newer v2 and builder APIs are generally more ergonomic.
  • Parser registration and parsing are single-threaded; handle_arguments(...) enforces the parser creation thread.
  • handle_arguments(...) resets the current convention list after it returns or throws.
  • Namespaces named argument_parser::internal::* are implementation details despite being present in public headers.