Skip to content

Commit fc4c414

Browse files
committed
Disallow calling certain functions after parse()
1 parent 1d50ee1 commit fc4c414

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

include/sharg/parser.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ class parser
240240
&& std::invocable<validator_type, option_type>
241241
void add_option(option_type & value, config<validator_type> const & config)
242242
{
243+
check_parse_not_called("add_option");
243244
verify_option_config(config);
244245

245246
// copy variables into the lambda because the calls are pushed to a stack
@@ -266,6 +267,7 @@ class parser
266267
requires std::invocable<validator_type, bool>
267268
void add_flag(bool & value, config<validator_type> const & config)
268269
{
270+
check_parse_not_called("add_flag");
269271
verify_flag_config(config);
270272

271273
if (value)
@@ -308,6 +310,7 @@ class parser
308310
&& std::invocable<validator_type, option_type>
309311
void add_positional_option(option_type & value, config<validator_type> const & config)
310312
{
313+
check_parse_not_called("add_positional_option");
311314
verify_positional_option_config(config);
312315

313316
if constexpr (detail::is_container_option<option_type>)
@@ -535,6 +538,7 @@ class parser
535538
*/
536539
void add_section(std::string const & title, bool const advanced_only = false)
537540
{
541+
check_parse_not_called("add_section");
538542
std::visit(
539543
[&title, advanced_only](auto & f)
540544
{
@@ -554,6 +558,7 @@ class parser
554558
*/
555559
void add_subsection(std::string const & title, bool const advanced_only = false)
556560
{
561+
check_parse_not_called("add_subsection");
557562
std::visit(
558563
[&title, advanced_only](auto & f)
559564
{
@@ -574,6 +579,7 @@ class parser
574579
*/
575580
void add_line(std::string const & text, bool is_paragraph = false, bool const advanced_only = false)
576581
{
582+
check_parse_not_called("add_line");
577583
std::visit(
578584
[&text, is_paragraph, advanced_only](auto & f)
579585
{
@@ -603,6 +609,7 @@ class parser
603609
*/
604610
void add_list_item(std::string const & key, std::string const & desc, bool const advanced_only = false)
605611
{
612+
check_parse_not_called("add_list_item");
606613
std::visit(
607614
[&key, &desc, advanced_only](auto & f)
608615
{
@@ -670,6 +677,7 @@ class parser
670677
*/
671678
void add_subcommands(std::vector<std::string> const & subcommands)
672679
{
680+
check_parse_not_called("add_subcommands");
673681
for (auto const & sub : subcommands)
674682
{
675683
if (!std::regex_match(sub, app_name_regex))
@@ -1016,6 +1024,21 @@ class parser
10161024
if (!config.default_message.empty())
10171025
throw design_error{"A positional option may not have a default message because it is always required."};
10181026
}
1027+
1028+
/*!\brief Throws a sharg::design_error if parse() was already called.
1029+
* \param[in] function_name The name of the function that was called after parse().
1030+
* \throws sharg::design_error
1031+
* \details
1032+
* This function is used when calling functions which have no effect (add_line, add_option, ...) or unexpected
1033+
* behavior (add_subcommands) after parse() was called.
1034+
* Has no effect when parse() encounters a special format (help, version, ...), since those will terminate
1035+
* the program.
1036+
*/
1037+
inline void check_parse_not_called(std::string_view const function_name) const
1038+
{
1039+
if (parse_was_called)
1040+
throw design_error{detail::to_string(function_name.data(), " may only be used before calling parse().")};
1041+
}
10191042
};
10201043

10211044
} // namespace sharg

0 commit comments

Comments
 (0)