mirror of
https://github.com/sametersoylu/argument-parser.git
synced 2026-07-14 01:28:13 +00:00
chore: separate assertions from builder header
This commit is contained in:
@@ -8,5 +8,5 @@ NamespaceIndentation: All
|
|||||||
AccessModifierOffset: -4
|
AccessModifierOffset: -4
|
||||||
BreakBeforeBraces: Attach
|
BreakBeforeBraces: Attach
|
||||||
AllowShortFunctionsOnASingleLine: Empty
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
ColumnLimit: 120
|
ColumnLimit: 180
|
||||||
...
|
...
|
||||||
|
|||||||
@@ -15,16 +15,7 @@ namespace argument_parser::builder {
|
|||||||
namespace builder_mask {
|
namespace builder_mask {
|
||||||
using v2_flag = argument_parser::v2::add_argument_flags;
|
using v2_flag = argument_parser::v2::add_argument_flags;
|
||||||
using mask_type = std::uint64_t;
|
using mask_type = std::uint64_t;
|
||||||
enum class value_mode {
|
enum class value_mode { unresolved, store, flag, reference, accumulate, count, action_no_param, action_with_param };
|
||||||
unresolved,
|
|
||||||
store,
|
|
||||||
flag,
|
|
||||||
reference,
|
|
||||||
accumulate,
|
|
||||||
count,
|
|
||||||
action_no_param,
|
|
||||||
action_with_param
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class extra_capability : unsigned { Store = static_cast<unsigned>(v2_flag::Reference) + 1, Flag };
|
enum class extra_capability : unsigned { Store = static_cast<unsigned>(v2_flag::Reference) + 1, Flag };
|
||||||
|
|
||||||
@@ -45,15 +36,13 @@ namespace argument_parser::builder {
|
|||||||
constexpr mask_type required = bit(v2_flag::Required);
|
constexpr mask_type required = bit(v2_flag::Required);
|
||||||
constexpr mask_type reference = bit(v2_flag::Reference);
|
constexpr mask_type reference = bit(v2_flag::Reference);
|
||||||
constexpr mask_type accumulate = bit(v2_flag::Accumulate);
|
constexpr mask_type accumulate = bit(v2_flag::Accumulate);
|
||||||
constexpr mask_type count = bit(
|
constexpr mask_type count =
|
||||||
static_cast<v2_flag>(static_cast<int>(v2_flag::Accumulate) + (static_cast<int>(extra_capability::Store) |
|
bit(static_cast<v2_flag>(static_cast<int>(v2_flag::Accumulate) + (static_cast<int>(extra_capability::Store) | static_cast<int>(extra_capability::Flag))));
|
||||||
static_cast<int>(extra_capability::Flag))));
|
|
||||||
constexpr mask_type store = bit(extra_capability::Store);
|
constexpr mask_type store = bit(extra_capability::Store);
|
||||||
constexpr mask_type flag = bit(extra_capability::Flag);
|
constexpr mask_type flag = bit(extra_capability::Flag);
|
||||||
|
|
||||||
constexpr mask_type value_mode_group = action | reference | accumulate | count | store | flag;
|
constexpr mask_type value_mode_group = action | reference | accumulate | count | store | flag;
|
||||||
constexpr mask_type initial = short_argument | long_argument | positional | help_text | action | required |
|
constexpr mask_type initial = short_argument | long_argument | positional | help_text | action | required | reference | accumulate | count | store | flag;
|
||||||
reference | accumulate | count | store | flag;
|
|
||||||
|
|
||||||
constexpr mask_type storable_mode_group = (count | store | flag | accumulate | reference) >> 1;
|
constexpr mask_type storable_mode_group = (count | store | flag | accumulate | reference) >> 1;
|
||||||
|
|
||||||
@@ -125,50 +114,34 @@ namespace argument_parser::builder {
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::short_argument), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::short_argument), int> = 0>
|
|
||||||
auto short_argument(std::string short_name) const
|
auto short_argument(std::string short_name) const
|
||||||
-> argument<builder_mask::replace(current_mask, builder_mask::short_argument | builder_mask::positional |
|
-> argument<builder_mask::replace(current_mask, builder_mask::short_argument | builder_mask::positional | builder_mask::position), store_type> {
|
||||||
builder_mask::position),
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::short_argument | builder_mask::positional | builder_mask::position), store_type>;
|
||||||
store_type> {
|
|
||||||
using next_argument =
|
|
||||||
argument<builder_mask::replace(current_mask, builder_mask::short_argument | builder_mask::positional |
|
|
||||||
builder_mask::position),
|
|
||||||
store_type>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_short_argument = std::move(short_name);
|
next.m_short_argument = std::move(short_name);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::long_argument), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::long_argument), int> = 0>
|
|
||||||
auto long_argument(std::string long_name) const
|
auto long_argument(std::string long_name) const
|
||||||
-> argument<builder_mask::replace(current_mask, builder_mask::long_argument | builder_mask::positional |
|
-> argument<builder_mask::replace(current_mask, builder_mask::long_argument | builder_mask::positional | builder_mask::position), store_type> {
|
||||||
builder_mask::position),
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::long_argument | builder_mask::positional | builder_mask::position), store_type>;
|
||||||
store_type> {
|
|
||||||
using next_argument =
|
|
||||||
argument<builder_mask::replace(current_mask, builder_mask::long_argument | builder_mask::positional |
|
|
||||||
builder_mask::position),
|
|
||||||
store_type>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_long_argument = std::move(long_name);
|
next.m_long_argument = std::move(long_name);
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::positional), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::positional), int> = 0>
|
|
||||||
auto positional(std::string positional_name) const
|
auto positional(std::string positional_name) const
|
||||||
-> argument<builder_mask::replace(current_mask,
|
-> argument<builder_mask::replace(current_mask, builder_mask::short_argument | builder_mask::long_argument | builder_mask::positional | builder_mask::flag,
|
||||||
builder_mask::short_argument | builder_mask::long_argument |
|
|
||||||
builder_mask::positional | builder_mask::flag,
|
|
||||||
builder_mask::position),
|
builder_mask::position),
|
||||||
store_type> {
|
store_type> {
|
||||||
using next_argument =
|
using next_argument =
|
||||||
argument<builder_mask::replace(current_mask,
|
argument<builder_mask::replace(current_mask,
|
||||||
builder_mask::short_argument | builder_mask::long_argument |
|
builder_mask::short_argument | builder_mask::long_argument | builder_mask::positional | builder_mask::flag | builder_mask::count,
|
||||||
builder_mask::positional | builder_mask::flag | builder_mask::count,
|
|
||||||
builder_mask::position),
|
builder_mask::position),
|
||||||
store_type>;
|
store_type>;
|
||||||
|
|
||||||
@@ -177,10 +150,8 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::position), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::position), int> = 0>
|
auto position(int index) const -> argument<builder_mask::remove(current_mask, builder_mask::position), store_type> {
|
||||||
auto position(int index) const
|
|
||||||
-> argument<builder_mask::remove(current_mask, builder_mask::position), store_type> {
|
|
||||||
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::position), store_type>;
|
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::position), store_type>;
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
@@ -188,10 +159,8 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::help_text), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::help_text), int> = 0>
|
auto help_text(std::string help) const -> argument<builder_mask::remove(current_mask, builder_mask::help_text), store_type> {
|
||||||
auto help_text(std::string help) const
|
|
||||||
-> argument<builder_mask::remove(current_mask, builder_mask::help_text), store_type> {
|
|
||||||
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::help_text), store_type>;
|
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::help_text), store_type>;
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
@@ -199,10 +168,8 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::required), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::required), int> = 0>
|
auto required(bool value = true) const -> argument<builder_mask::remove(current_mask, builder_mask::required), store_type> {
|
||||||
auto required(bool value = true) const
|
|
||||||
-> argument<builder_mask::remove(current_mask, builder_mask::required), store_type> {
|
|
||||||
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::required), store_type>;
|
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::required), store_type>;
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
@@ -210,11 +177,9 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = std::string, mask_type current_mask = mask,
|
template <typename T = std::string, mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::store), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::store), int> = 0>
|
|
||||||
auto store() const -> argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), T> {
|
auto store() const -> argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), T> {
|
||||||
static_assert(!std::is_same_v<T, void>,
|
static_assert(!std::is_same_v<T, void>, "store<void>() is not supported. Use flag() for boolean-style arguments.");
|
||||||
"store<void>() is not supported. Use flag() for boolean-style arguments.");
|
|
||||||
|
|
||||||
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};
|
||||||
@@ -222,31 +187,21 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = std::string, mask_type current_mask = mask,
|
template <typename T = std::string, mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::accumulate), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::accumulate), int> = 0>
|
auto accumulate() const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), std::vector<T>> {
|
||||||
auto accumulate() const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
std::vector<T>> {
|
|
||||||
using vector_type = std::vector<T>;
|
using vector_type = std::vector<T>;
|
||||||
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), vector_type>;
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
vector_type>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_value_mode = value_mode::accumulate;
|
next.m_value_mode = value_mode::accumulate;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::accumulate), int> = 0, typename T>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::accumulate), int> = 0, typename T>
|
auto accumulate(T &value) const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), T> {
|
||||||
auto accumulate(T &value) const -> argument<
|
static_assert(argument_parser::v2::deducers::is_vector_v<T>, "accumulate(target) requires a std::vector target.");
|
||||||
builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), T> {
|
|
||||||
static_assert(argument_parser::v2::deducers::is_vector_v<T>,
|
|
||||||
"accumulate(target) requires a std::vector target.");
|
|
||||||
|
|
||||||
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), T>;
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
T>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_reference = std::addressof(value);
|
next.m_reference = std::addressof(value);
|
||||||
@@ -254,29 +209,19 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::count), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::count), int> = 0>
|
auto count() const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), int> {
|
||||||
auto count() const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), int>;
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
int> {
|
|
||||||
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
int>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_value_mode = value_mode::count;
|
next.m_value_mode = value_mode::count;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::count), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::count), int> = 0>
|
auto count(int &value) const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), int> {
|
||||||
auto count(int &value) const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
int> {
|
|
||||||
|
|
||||||
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), int>;
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
int>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_reference = std::addressof(value);
|
next.m_reference = std::addressof(value);
|
||||||
@@ -284,27 +229,18 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::flag), int> = 0>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::flag), int> = 0>
|
auto flag() const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), bool> {
|
||||||
auto flag() const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), bool>;
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
bool> {
|
|
||||||
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
bool>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_value_mode = value_mode::flag;
|
next.m_value_mode = value_mode::flag;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::reference), int> = 0, typename T>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::reference), int> = 0, typename T>
|
auto reference(T &value) const -> argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), T> {
|
||||||
auto reference(T &value) const -> argument<
|
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), T>;
|
||||||
builder_mask::replace(current_mask, builder_mask::value_mode_group, builder_mask::storable_mode_group), T> {
|
|
||||||
using next_argument = argument<builder_mask::replace(current_mask, builder_mask::value_mode_group,
|
|
||||||
builder_mask::storable_mode_group),
|
|
||||||
T>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_reference = std::addressof(value);
|
next.m_reference = std::addressof(value);
|
||||||
@@ -312,34 +248,26 @@ namespace argument_parser::builder {
|
|||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::action), int> = 0, typename Callable>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::action), int> = 0, typename Callable>
|
auto action(Callable &&handler) const
|
||||||
auto action(Callable &&handler) const -> std::enable_if_t<
|
-> std::enable_if_t<std::is_invocable_r_v<void, Callable>, argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), non_type>> {
|
||||||
std::is_invocable_r_v<void, Callable>,
|
using next_argument = argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), non_type>;
|
||||||
argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), non_type>> {
|
|
||||||
using next_argument =
|
|
||||||
argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), non_type>;
|
|
||||||
|
|
||||||
next_argument next{*this};
|
next_argument next{*this};
|
||||||
next.m_action = std::make_shared<argument_parser::action_no_param>(
|
next.m_action = std::make_shared<argument_parser::action_no_param>(std::function<void()>(std::forward<Callable>(handler)));
|
||||||
std::function<void()>(std::forward<Callable>(handler)));
|
|
||||||
next.m_value_mode = value_mode::action_no_param;
|
next.m_value_mode = value_mode::action_no_param;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T = std::string, mask_type current_mask = mask,
|
template <typename T = std::string, mask_type current_mask = mask, std::enable_if_t<builder_mask::has(current_mask, builder_mask::action), int> = 0, typename Callable>
|
||||||
std::enable_if_t<builder_mask::has(current_mask, builder_mask::action), int> = 0, typename Callable>
|
|
||||||
auto action(Callable &&handler) const
|
auto action(Callable &&handler) const
|
||||||
-> std::enable_if_t<std::is_invocable_r_v<void, Callable, const T &>,
|
-> std::enable_if_t<std::is_invocable_r_v<void, Callable, const T &>, argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), T>> {
|
||||||
argument<builder_mask::remove(current_mask, builder_mask::value_mode_group), T>> {
|
static_assert(!std::is_same_v<T, void>, "action<void>(...) is not supported. Use action([] { ... }) instead.");
|
||||||
static_assert(!std::is_same_v<T, void>,
|
|
||||||
"action<void>(...) is not supported. Use action([] { ... }) instead.");
|
|
||||||
|
|
||||||
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_action = std::make_shared<argument_parser::action_with_param<T>>(
|
next.m_action = std::make_shared<argument_parser::action_with_param<T>>(std::function<void(const T &)>(std::forward<Callable>(handler)));
|
||||||
std::function<void(const T &)>(std::forward<Callable>(handler)));
|
|
||||||
next.m_value_mode = value_mode::action_with_param;
|
next.m_value_mode = value_mode::action_with_param;
|
||||||
return next;
|
return next;
|
||||||
}
|
}
|
||||||
@@ -392,8 +320,7 @@ namespace argument_parser::builder {
|
|||||||
throw std::logic_error("The builder reached build() without a supported terminal value mode.");
|
throw std::logic_error("The builder reached build() without a supported terminal value mode.");
|
||||||
}
|
}
|
||||||
|
|
||||||
template <mask_type current_mask = mask,
|
template <mask_type current_mask = mask, std::enable_if_t<builder_mask::is_build_and_gettable(current_mask), int> = 0>
|
||||||
std::enable_if_t<builder_mask::is_build_and_gettable(current_mask), int> = 0>
|
|
||||||
auto build_and_get(argument_parser::v2::base_parser &parser) const -> container<store_type> {
|
auto build_and_get(argument_parser::v2::base_parser &parser) const -> container<store_type> {
|
||||||
assert_has_identifier();
|
assert_has_identifier();
|
||||||
switch (m_value_mode) {
|
switch (m_value_mode) {
|
||||||
@@ -428,9 +355,8 @@ namespace argument_parser::builder {
|
|||||||
|
|
||||||
template <mask_type other_mask, typename other_store_type>
|
template <mask_type other_mask, typename other_store_type>
|
||||||
argument(argument<other_mask, other_store_type> const &other)
|
argument(argument<other_mask, other_store_type> const &other)
|
||||||
: m_short_argument(other.m_short_argument), m_long_argument(other.m_long_argument),
|
: m_short_argument(other.m_short_argument), m_long_argument(other.m_long_argument), m_positional_name(other.m_positional_name), m_position(other.m_position),
|
||||||
m_positional_name(other.m_positional_name), m_position(other.m_position), m_help_text(other.m_help_text),
|
m_help_text(other.m_help_text), m_required(other.m_required), m_action(other.m_action), m_reference(copy_reference(other.m_reference)),
|
||||||
m_required(other.m_required), m_action(other.m_action), m_reference(copy_reference(other.m_reference)),
|
|
||||||
m_value_mode(other.m_value_mode) {}
|
m_value_mode(other.m_value_mode) {}
|
||||||
|
|
||||||
template <typename T> using typed_map = std::unordered_map<v2_flag, v2::base_parser::typed_flag_value<T>>;
|
template <typename T> using typed_map = std::unordered_map<v2_flag, v2::base_parser::typed_flag_value<T>>;
|
||||||
@@ -536,8 +462,7 @@ namespace argument_parser::builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto build_action_with_param(argument_parser::v2::base_parser &parser) const -> void {
|
auto build_action_with_param(argument_parser::v2::base_parser &parser) const -> void {
|
||||||
auto const *typed_action =
|
auto const *typed_action = dynamic_cast<argument_parser::action_with_param<store_type> const *>(m_action.get());
|
||||||
dynamic_cast<argument_parser::action_with_param<store_type> const *>(m_action.get());
|
|
||||||
if (typed_action == nullptr) {
|
if (typed_action == nullptr) {
|
||||||
throw std::logic_error("Stored action is not compatible with the requested parameter type.");
|
throw std::logic_error("Stored action is not compatible with the requested parameter type.");
|
||||||
}
|
}
|
||||||
@@ -554,8 +479,7 @@ namespace argument_parser::builder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (is_positional()) {
|
if (is_positional()) {
|
||||||
auto wrapped_action = argument_parser::helpers::make_action<std::string>(
|
auto wrapped_action = argument_parser::helpers::make_action<std::string>([action = *nonparametered_action](std::string const &) { action.invoke(); });
|
||||||
[action = *nonparametered_action](std::string const &) { action.invoke(); });
|
|
||||||
auto pairs = make_typed_pairs<std::string>();
|
auto pairs = make_typed_pairs<std::string>();
|
||||||
pairs[argument_parser::v2::flags::Action] = wrapped_action;
|
pairs[argument_parser::v2::flags::Action] = wrapped_action;
|
||||||
parser.template add_argument<std::string>(pairs);
|
parser.template add_argument<std::string>(pairs);
|
||||||
@@ -592,88 +516,6 @@ namespace argument_parser::builder {
|
|||||||
return argument<>::start();
|
return argument<>::start();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace assertions {
|
|
||||||
struct noop_handler {
|
|
||||||
void operator()() const {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T> struct parameter_sink {
|
|
||||||
void operator()(T const &) const {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename T, typename = void> struct can_use_help_text : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct can_use_help_text<T, std::void_t<decltype(std::declval<T>().help_text(std::declval<std::string>()))>>
|
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename = void> struct can_use_position : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct can_use_position<T, std::void_t<decltype(std::declval<T>().position(0))>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename = void> struct can_use_nonparametered_action : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct can_use_nonparametered_action<T, std::void_t<decltype(std::declval<T>().action(noop_handler{}))>>
|
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename U, typename = void> struct can_use_parametered_action : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
|
||||||
struct can_use_parametered_action<
|
|
||||||
T, U, std::void_t<decltype(std::declval<T>().template action<U>(parameter_sink<U>{}))>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename U, typename = void> struct can_use_store : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
|
||||||
struct can_use_store<T, U, std::void_t<decltype(std::declval<T>().template store<U>())>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename = void> struct can_use_flag : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct can_use_flag<T, std::void_t<decltype(std::declval<T>().flag())>> : std::true_type {};
|
|
||||||
|
|
||||||
template <typename T, typename U, typename = void> struct can_use_reference : std::false_type {};
|
|
||||||
|
|
||||||
template <typename T, typename U>
|
|
||||||
struct can_use_reference<T, U, std::void_t<decltype(std::declval<T>().reference(std::declval<U &>()))>>
|
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
using after_help_text = decltype(argument<>::start().help_text("help"));
|
|
||||||
static_assert(!can_use_help_text<after_help_text>::value, "help_text() should be single-use.");
|
|
||||||
|
|
||||||
using after_positional = decltype(argument<>::start().positional("path"));
|
|
||||||
static_assert(can_use_position<after_positional>::value, "positional() should unlock position().");
|
|
||||||
|
|
||||||
using after_position = decltype(argument<>::start().positional("path").position(0));
|
|
||||||
static_assert(!can_use_position<after_position>::value, "position() should be single-use.");
|
|
||||||
|
|
||||||
using after_positional_mode_selection = decltype(argument<>::start().positional("path").store<>());
|
|
||||||
static_assert(!can_use_flag<after_positional_mode_selection>::value,
|
|
||||||
"flag() should not be available for positional arguments.");
|
|
||||||
|
|
||||||
using after_nonparametered_action =
|
|
||||||
decltype(argument<>::start().short_argument("v").help_text("verbose").action(noop_handler{}));
|
|
||||||
static_assert(!can_use_nonparametered_action<after_nonparametered_action>::value,
|
|
||||||
"action() should not remain callable after selecting a non-parametered action.");
|
|
||||||
static_assert(!can_use_parametered_action<after_nonparametered_action, int>::value,
|
|
||||||
"typed action() should also be disabled after selecting a non-parametered action.");
|
|
||||||
static_assert(!can_use_store<after_nonparametered_action, int>::value,
|
|
||||||
"store() should be mutually exclusive with action().");
|
|
||||||
static_assert(!can_use_flag<after_nonparametered_action>::value,
|
|
||||||
"flag() should be mutually exclusive with action().");
|
|
||||||
static_assert(!can_use_reference<after_nonparametered_action, int>::value,
|
|
||||||
"reference() should be mutually exclusive with action().");
|
|
||||||
|
|
||||||
using after_parametered_action =
|
|
||||||
decltype(argument<>::start().positional("count").position(0).action<int>(parameter_sink<int>{}));
|
|
||||||
static_assert(!can_use_nonparametered_action<after_parametered_action>::value,
|
|
||||||
"non-parametered action() should be disabled after selecting a typed action.");
|
|
||||||
static_assert(!can_use_parametered_action<after_parametered_action, std::string>::value,
|
|
||||||
"typed action() should be single-use regardless of the parameter type.");
|
|
||||||
|
|
||||||
} // namespace assertions
|
|
||||||
} // namespace argument_parser::builder
|
} // namespace argument_parser::builder
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
68
src/source/parser/argument_builder.cpp
Normal file
68
src/source/parser/argument_builder.cpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#include <argument_builder.hpp>
|
||||||
|
#include <parser_v2.hpp>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace argument_parser::builder {
|
||||||
|
namespace assertions {
|
||||||
|
struct noop_handler {
|
||||||
|
void operator()() const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T> struct parameter_sink {
|
||||||
|
void operator()(T const &) const {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, typename = void> struct can_use_help_text : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T> struct can_use_help_text<T, std::void_t<decltype(std::declval<T>().help_text(std::declval<std::string>()))>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T, typename = void> struct can_use_position : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T> struct can_use_position<T, std::void_t<decltype(std::declval<T>().position(0))>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T, typename = void> struct can_use_nonparametered_action : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T> struct can_use_nonparametered_action<T, std::void_t<decltype(std::declval<T>().action(noop_handler{}))>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T, typename U, typename = void> struct can_use_parametered_action : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T, typename U>
|
||||||
|
struct can_use_parametered_action<T, U, std::void_t<decltype(std::declval<T>().template action<U>(parameter_sink<U>{}))>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T, typename U, typename = void> struct can_use_store : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T, typename U> struct can_use_store<T, U, std::void_t<decltype(std::declval<T>().template store<U>())>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T, typename = void> struct can_use_flag : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T> struct can_use_flag<T, std::void_t<decltype(std::declval<T>().flag())>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T, typename U, typename = void> struct can_use_reference : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T, typename U> struct can_use_reference<T, U, std::void_t<decltype(std::declval<T>().reference(std::declval<U &>()))>> : std::true_type {};
|
||||||
|
|
||||||
|
using after_help_text = decltype(argument<>::start().help_text("help"));
|
||||||
|
static_assert(!can_use_help_text<after_help_text>::value, "help_text() should be single-use.");
|
||||||
|
|
||||||
|
using after_positional = decltype(argument<>::start().positional("path"));
|
||||||
|
static_assert(can_use_position<after_positional>::value, "positional() should unlock position().");
|
||||||
|
|
||||||
|
using after_position = decltype(argument<>::start().positional("path").position(0));
|
||||||
|
static_assert(!can_use_position<after_position>::value, "position() should be single-use.");
|
||||||
|
|
||||||
|
using after_positional_mode_selection = decltype(argument<>::start().positional("path").store<>());
|
||||||
|
static_assert(!can_use_flag<after_positional_mode_selection>::value, "flag() should not be available for positional arguments.");
|
||||||
|
|
||||||
|
using after_nonparametered_action = decltype(argument<>::start().short_argument("v").help_text("verbose").action(noop_handler{}));
|
||||||
|
static_assert(!can_use_nonparametered_action<after_nonparametered_action>::value, "action() should not remain callable after selecting a non-parametered action.");
|
||||||
|
static_assert(!can_use_parametered_action<after_nonparametered_action, int>::value, "typed action() should also be disabled after selecting a non-parametered action.");
|
||||||
|
static_assert(!can_use_store<after_nonparametered_action, int>::value, "store() should be mutually exclusive with action().");
|
||||||
|
static_assert(!can_use_flag<after_nonparametered_action>::value, "flag() should be mutually exclusive with action().");
|
||||||
|
static_assert(!can_use_reference<after_nonparametered_action, int>::value, "reference() should be mutually exclusive with action().");
|
||||||
|
|
||||||
|
using after_parametered_action = decltype(argument<>::start().positional("count").position(0).action<int>(parameter_sink<int>{}));
|
||||||
|
static_assert(!can_use_nonparametered_action<after_parametered_action>::value, "non-parametered action() should be disabled after selecting a typed action.");
|
||||||
|
static_assert(!can_use_parametered_action<after_parametered_action, std::string>::value, "typed action() should be single-use regardless of the parameter type.");
|
||||||
|
|
||||||
|
} // namespace assertions
|
||||||
|
} // namespace argument_parser::builder
|
||||||
Reference in New Issue
Block a user