|
|
@@ -39,7 +39,7 @@ public:
|
|
|
return {arguments.begin() + argument_names.size(), arguments.end()};
|
|
|
}
|
|
|
|
|
|
- // protected:
|
|
|
+protected:
|
|
|
template <typename T> Arguments(T const * parent) : parent_(parent) {}
|
|
|
template <typename T>
|
|
|
Arguments(int argc, char const * const * const argv, T const * parent);
|
|
|
@@ -147,8 +147,15 @@ private:
|
|
|
// A helper for what limited introspection is required for handling actions in
|
|
|
// test
|
|
|
friend struct ArgumentTestHelper;
|
|
|
+ template <typename> friend class Arguments;
|
|
|
friend int main(int, char const * const *);
|
|
|
|
|
|
+ operator bool() const { return primed_; }
|
|
|
+
|
|
|
+ template <typename... Parents> int invoke(Parents const &... parents) const {
|
|
|
+ return typed_main(parents..., static_cast<Impl const &>(*this));
|
|
|
+ }
|
|
|
+
|
|
|
template <typename T>
|
|
|
std::shared_ptr<T> make_action(std::string const & name) const {
|
|
|
if (action_name_ != name) { return nullptr; }
|
|
|
@@ -157,9 +164,8 @@ private:
|
|
|
}
|
|
|
|
|
|
private:
|
|
|
- using main_callback_t = std::function<int(Impl const &)>;
|
|
|
using make_action_t = std::function<std::shared_ptr<void>(Impl const &)>;
|
|
|
- using make_hook_t =
|
|
|
+ using action_hook_t =
|
|
|
std::function<make_action_t(size_t, char const * const *)>;
|
|
|
// Metadata variables
|
|
|
bool primed_{false};
|
|
|
@@ -170,14 +176,13 @@ private:
|
|
|
std::map<option_id, std::string> option_descriptions;
|
|
|
std::map<std::string, option_id> option_names;
|
|
|
std::set<option_id> flag_names;
|
|
|
- std::map<std::string, make_hook_t> actions;
|
|
|
+ std::map<std::string, action_hook_t> actions;
|
|
|
std::string action_name_{""};
|
|
|
make_action_t make_action_{nullptr};
|
|
|
std::map<std::string, std::string> action_descriptions;
|
|
|
|
|
|
// Data/Output variables
|
|
|
std::string program;
|
|
|
- main_callback_t main_callback{nullptr};
|
|
|
constexpr static size_t const no_optional_args{~0ul};
|
|
|
size_t optional_from{no_optional_args};
|
|
|
std::vector<std::string> arguments;
|
|
|
@@ -250,9 +255,24 @@ struct Arguments<Impl>::WithDefault {
|
|
|
template <typename Args, typename... Actions>
|
|
|
int typed_main(Args const &, Actions const &...);
|
|
|
|
|
|
+#include <boost/preprocessor.hpp>
|
|
|
+
|
|
|
+#define TRY_INVOKE(r, data, elem) \
|
|
|
+ if (self.elem) { return self.elem.invoke(parents..., self); }
|
|
|
+
|
|
|
+#define PROGRAM_ARGS_INVOKE(tname, ...) \
|
|
|
+ template <> \
|
|
|
+ template <typename... Parents> \
|
|
|
+ int program::Arguments<tname>::invoke(Parents const &... parents) const { \
|
|
|
+ tname const & self = static_cast<tname const &>(*this); \
|
|
|
+ BOOST_PP_SEQ_FOR_EACH(TRY_INVOKE, _, \
|
|
|
+ BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
|
|
|
+ throw program::ProgramArgumentsError("no valid action provided"); \
|
|
|
+ }
|
|
|
+
|
|
|
#define PROGRAM_ARGS_MAIN(tname) \
|
|
|
int main(int argc, char const * const * const argv) try { \
|
|
|
- tname(argc, argv).invoke(); \
|
|
|
+ return tname(argc, argv).invoke(); \
|
|
|
} catch (program::ProgramArgumentsError const & pae) { \
|
|
|
std::cerr << "Error in program argument handling: " << pae.what() << "\n"; \
|
|
|
}
|