Skip to content

Use std::variant instead of std::any and std::array instead of std::unordered_map #26

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 17, 2024

Conversation

rsore
Copy link
Owner

@rsore rsore commented Sep 17, 2024

Description

This branch introduces a new container for parsed values and a more efficient retrieval method, replacing the current implementation.

In the existing code, parsed values are stored in a std::unordered_map and type-erased using std::any. This approach has several drawbacks:

  • Dynamic Allocation: Values are dynamically allocated on the heap, leading to potential performance overhead.
  • Type Safety: Using std::any for type erasure is inherently unsafe.
  • Lookup Overhead: Retrieving values from a std::unordered_map indexed by std::type_index can involve costly lookups and may require resolving hash conflicts.

This branch improves upon this by storing each parsed value in a std::optional with the actual ValueType specified in the option type. The values are stored in a contiguous std::array whose size matches the number of flags and options passed to the parser. To support multiple value types, the array’s underlying type is a std::variant capable of holding any permutation of std::optional<ValueType>.

Consider the following example:

using FooOption= CLArgs::Option<"--foo", "<hint>", "<description>", int>;
using BarOption= CLArgs::Option<"--bar", "<hint>", "<description>", float>;
using BazOption= CLArgs::Option<"--baz", "<hint>", "<description>", int>;
CLArgs::Parser<FooOption, BarOption, BazOption> parser;

In this example, the value types are int, float, and int. Duplicate types are filtered out, so the container type becomes:

std::array<std::variant<std::optional<int>, std::optional<float>>, 3>

Values are stored in the array in the order they were passed to the parser, ensuring type safety and eliminating hash lookups. Accessing values is as simple as indexing directly into the array, with the index determined at compile-time.

All logic related to this new container is encapsulated in a ValueContainer class, which is used by the Parser.

Related Issues

Closes #3.

@rsore rsore added the improvement Improvement to existing feature label Sep 17, 2024
@rsore rsore linked an issue Sep 17, 2024 that may be closed by this pull request
Copy link

clang-tidy review says "All clean, LGTM! 👍"

@rsore rsore merged commit 224456b into main Sep 17, 2024
7 checks passed
@rsore rsore deleted the 3-use-stdvariant-instead-of-stdany branch September 17, 2024 22:25
rsore added a commit that referenced this pull request Oct 20, 2024
Use std::variant instead of std::any and std::array instead of std::unordered_map
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improvement Improvement to existing feature
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use std::variant instead of std::any
1 participant