argparser/src/optional-arg.h
2023-05-17 10:17:56 +02:00

67 lines
1.9 KiB
C++

#ifndef ARGPARSER_OPTIONAL_ARG_H
#define ARGPARSER_OPTIONAL_ARG_H
#include "argument.h"
#include "errors.h"
#include "parse-result.h"
#include "type.h"
#include <any>
#include <cassert>
#include <memory>
#include <optional>
#include <span>
#include <string>
namespace argparser {
template<typename T>
class optional_arg : public arg, public std::enable_shared_from_this<optional_arg<T>> {
public:
optional_arg(std::string name, type_handle_impl<T> type) : arg(std::move(name)), type(type) {}
std::shared_ptr<optional_arg<T>> default_value(T val) {
default_value_ = val;
return this->shared_from_this();
}
[[nodiscard]] std::optional<T> get(const parse_result &p) const {
auto v = p.get_arg(name);
if (!v.has_value()) {
if (default_value_.has_value()) {
return default_value_.value();
}
return std::nullopt;
}
return std::make_optional(std::any_cast<T>(v));
}
[[nodiscard]] bool has(const parse_result &p) const {
return p.has_arg(name);
}
private:
type_handle_impl<T> type;
std::optional<T> default_value_ = std::nullopt;
void do_parse(std::string input, parse_result &pr) const override {
assert(!pr.get_arg(name).has_value());// an optional arg can only be parsed once
auto val = this->parse_single_value(input, type);
pr.set_arg(name, std::make_any<T>(val));
}
[[nodiscard]] bool get_can_parse_more(parse_result &pr) const override {
return !pr.get_arg(name).has_value();
}
[[nodiscard]] bool get_has_parsed_enough(parse_result &) const override {
return true;
}
};
template<typename T>
using optional_arg_handle = std::shared_ptr<optional_arg<T>>;
}// namespace argparser
#endif//ARGPARSER_OPTIONAL_ARG_H