chore: separate assertions from builder header

This commit is contained in:
2026-06-01 14:06:51 +04:00
parent 1015b66d80
commit 7b3758caa3
3 changed files with 129 additions and 219 deletions

View 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