mirror of
https://github.com/sametersoylu/argument-parser.git
synced 2026-05-28 20:08:10 +00:00
feat: implement reference capture mode.
This commit is contained in:
@@ -3,6 +3,7 @@
|
|||||||
#include <gnu_argument_convention.hpp>
|
#include <gnu_argument_convention.hpp>
|
||||||
#include <macros.h>
|
#include <macros.h>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <parser_v2.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <traits.hpp>
|
#include <traits.hpp>
|
||||||
|
|
||||||
@@ -44,6 +45,8 @@ class parser_trait<std::vector<T>> {
|
|||||||
>;
|
>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
using namespace argument_parser::v2::flags;
|
||||||
|
|
||||||
auto main() -> int {
|
auto main() -> int {
|
||||||
argument_parser::v2::parser parser(false);
|
argument_parser::v2::parser parser(false);
|
||||||
|
|
||||||
@@ -63,6 +66,12 @@ auto main() -> int {
|
|||||||
.reference(captured_value)
|
.reference(captured_value)
|
||||||
.build(parser);
|
.build(parser);
|
||||||
|
|
||||||
|
// parser.add_argument<int>({
|
||||||
|
// {ShortArgument, "c"},
|
||||||
|
// {HelpText, "capture count"},
|
||||||
|
// {Reference, &captured_value},
|
||||||
|
// });
|
||||||
|
|
||||||
argument::start()
|
argument::start()
|
||||||
.short_argument("q")
|
.short_argument("q")
|
||||||
.help_text("Store a boolean flag.")
|
.help_text("Store a boolean flag.")
|
||||||
@@ -95,5 +104,7 @@ auto main() -> int {
|
|||||||
&argument_parser::conventions::gnu_argument_convention
|
&argument_parser::conventions::gnu_argument_convention
|
||||||
});
|
});
|
||||||
|
|
||||||
|
std::cout << "captured value: " << captured_value << '\n';
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ public:
|
|||||||
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), T>;
|
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), T>;
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_reference = static_cast<void*>(std::addressof(value));
|
next.m_reference = std::addressof(value);
|
||||||
next.m_value_mode = value_mode::reference;
|
next.m_value_mode = value_mode::reference;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,7 @@ private:
|
|||||||
m_help_text(other.m_help_text),
|
m_help_text(other.m_help_text),
|
||||||
m_required(other.m_required),
|
m_required(other.m_required),
|
||||||
m_action(other.m_action),
|
m_action(other.m_action),
|
||||||
m_reference(other.m_reference),
|
m_reference(copy_reference(other.m_reference)),
|
||||||
m_value_mode(other.m_value_mode) {}
|
m_value_mode(other.m_value_mode) {}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -361,7 +361,7 @@ private:
|
|||||||
|
|
||||||
auto build_reference(argument_parser::v2::base_parser& parser) const -> void {
|
auto build_reference(argument_parser::v2::base_parser& parser) const -> void {
|
||||||
auto pairs = make_typed_pairs<store_type>();
|
auto pairs = make_typed_pairs<store_type>();
|
||||||
auto* target = static_cast<store_type*>(m_reference);
|
auto* target = m_reference;
|
||||||
auto key = lookup_key();
|
auto key = lookup_key();
|
||||||
|
|
||||||
if (target == nullptr) {
|
if (target == nullptr) {
|
||||||
@@ -414,9 +414,18 @@ private:
|
|||||||
std::string m_help_text{};
|
std::string m_help_text{};
|
||||||
bool m_required = false;
|
bool m_required = false;
|
||||||
std::shared_ptr<argument_parser::action_base const> m_action{};
|
std::shared_ptr<argument_parser::action_base const> m_action{};
|
||||||
void* m_reference = nullptr;
|
store_type* m_reference = nullptr;
|
||||||
value_mode m_value_mode = value_mode::unresolved;
|
value_mode m_value_mode = value_mode::unresolved;
|
||||||
|
|
||||||
|
template<typename other_store_type>
|
||||||
|
static auto copy_reference(other_store_type* reference) -> store_type* {
|
||||||
|
if constexpr (std::is_same_v<store_type, other_store_type>) {
|
||||||
|
return reference;
|
||||||
|
} else {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<mask_type other_mask, typename other_store_type>
|
template<mask_type other_mask, typename other_store_type>
|
||||||
friend class argument;
|
friend class argument;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
#include <type_traits>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -29,7 +30,7 @@ namespace argument_parser::v2 {
|
|||||||
|
|
||||||
class base_parser : private argument_parser::base_parser {
|
class base_parser : private argument_parser::base_parser {
|
||||||
public:
|
public:
|
||||||
template <typename T> using typed_flag_value = std::variant<std::string, parametered_action<T>, bool, int>;
|
template <typename T> using typed_flag_value = std::variant<std::string, parametered_action<T>, bool, int, T*>;
|
||||||
using non_typed_flag_value = std::variant<std::string, non_parametered_action, bool, int>;
|
using non_typed_flag_value = std::variant<std::string, non_parametered_action, bool, int>;
|
||||||
|
|
||||||
template <typename T> using typed_argument_pair = std::pair<add_argument_flags, typed_flag_value<T>>;
|
template <typename T> using typed_argument_pair = std::pair<add_argument_flags, typed_flag_value<T>>;
|
||||||
@@ -145,6 +146,22 @@ namespace argument_parser::v2 {
|
|||||||
required = true;
|
required = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (argument_pairs.find(add_argument_flags::Reference) != argument_pairs.end()) {
|
||||||
|
if (!IsTyped) {
|
||||||
|
throw std::logic_error("Reference argument must be typed");
|
||||||
|
}
|
||||||
|
|
||||||
|
found_params[extended_add_argument_flags::Action] = true;
|
||||||
|
if constexpr (!std::is_same_v<T, void>) {
|
||||||
|
auto ref = get_or_throw<T*>(argument_pairs.at(add_argument_flags::Reference), "reference");
|
||||||
|
action = helpers::make_parametered_action<T>([ref](T const& t) {
|
||||||
|
*ref = t;
|
||||||
|
}).clone();
|
||||||
|
} else {
|
||||||
|
throw std::logic_error("Reference argument must not be void");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto suggested_add = suggest_candidate(found_params);
|
auto suggested_add = suggest_candidate(found_params);
|
||||||
if (suggested_add == candidate_type::unknown) {
|
if (suggested_add == candidate_type::unknown) {
|
||||||
throw std::runtime_error("Could not match any add argument overload to given parameters. Are you "
|
throw std::runtime_error("Could not match any add argument overload to given parameters. Are you "
|
||||||
@@ -166,8 +183,7 @@ namespace argument_parser::v2 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
base::add_argument(short_arg, long_arg, help_text, *static_cast<ActionType *>(&(*action)),
|
base::add_argument(short_arg, long_arg, help_text, *static_cast<ActionType *>(&(*action)), required);
|
||||||
required);
|
|
||||||
break;
|
break;
|
||||||
case candidate_type::store_other:
|
case candidate_type::store_other:
|
||||||
if (help_text.empty()) {
|
if (help_text.empty()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user