Auto.hpp
1 // Distributed under the MIT License.
2 // See LICENSE.txt for details.
3 
4 #pragma once
5 
6 #include <optional>
7 #include <ostream>
8 #include <string>
9 #include <utility>
10 
11 #include "Options/Options.hpp"
12 #include "Utilities/GetOutput.hpp"
13 
14 namespace Options {
15 /// The label representing the absence of a value for `Options::Auto`
16 enum class AutoLabel { Auto, None };
17 
18 std::ostream& operator<<(std::ostream& os, AutoLabel label) noexcept;
19 
20 /// \ingroup OptionParsingGroup
21 /// \brief A class indicating that a parsed value can be automatically
22 /// computed instead of specified.
23 ///
24 /// When an `Auto<T>` is parsed from an input file, the value may be specified
25 /// either as the `AutoLabel` (defaults to "Auto") or as a value of type `T`.
26 /// When this class is passed to the constructor of the class taking it as an
27 /// option, it can be implicitly converted to a `std::optional<T>`.
28 ///
29 /// \snippet Test_Auto.cpp example_class
30 /// \snippet Test_Auto.cpp example_create
31 template <typename T, AutoLabel Label = AutoLabel::Auto>
32 class Auto {
33  public:
34  Auto() = default;
35  explicit Auto(T value) noexcept : value_(std::move(value)) {}
36 
37  // NOLINTNEXTLINE(google-explicit-constructor)
38  operator std::optional<T>() && { return std::move(value_); }
39 
40  // NOLINTNEXTLINE(google-explicit-constructor)
41  operator const std::optional<T>&() const { return value_; }
42 
43  private:
44  std::optional<T> value_{};
45 };
46 
47 template <typename T, AutoLabel Label>
48 bool operator==(const Auto<T, Label>& a, const Auto<T, Label>& b) noexcept {
49  return static_cast<const std::optional<T>&>(a) ==
50  static_cast<const std::optional<T>&>(b);
51 }
52 
53 template <typename T, AutoLabel Label>
54 bool operator!=(const Auto<T, Label>& a, const Auto<T, Label>& b) noexcept {
55  return not(a == b);
56 }
57 
58 template <typename T, AutoLabel Label>
59 std::ostream& operator<<(std::ostream& os, const Auto<T, Label>& x) noexcept {
60  const std::optional<T>& value = x;
61  if (value) {
62  return os << get_output(*value);
63  } else {
64  return os << Label;
65  }
66 }
67 
68 template <typename T, AutoLabel Label>
69 struct create_from_yaml<Auto<T, Label>> {
70  template <typename Metavariables>
71  static Auto<T, Label> create(const Option& options) {
72  try {
73  if (options.parse_as<std::string>() == get_output(Label)) {
74 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
75 #pragma GCC diagnostic push
76 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
77 #endif // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__ < 10
78  return {};
79 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
80 #pragma GCC diagnostic pop
81 #endif // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__ < 10
82  }
83  } catch (...) {
84  // The node failed to parse as a string. It is not the AutoLabel.
85  }
86  return Auto<T, Label>{options.parse_as<T>()};
87  }
88 };
89 } // namespace Options
std::string
utility
Options.hpp
get_output
std::string get_output(const T &t) noexcept
Get the streamed output of t as a std::string
Definition: GetOutput.hpp:14
Options::Option
Definition: Options.hpp:108
Options
Utilities for parsing input files.
Definition: MinmodType.hpp:8
std::ostream
Options::create_from_yaml
Definition: MinmodType.hpp:11
Options::AutoLabel
AutoLabel
The label representing the absence of a value for Options::Auto
Definition: Auto.hpp:16
Options::Auto
A class indicating that a parsed value can be automatically computed instead of specified.
Definition: Auto.hpp:32
Options::Option::parse_as
T parse_as() const
Convert to an object of type T.
Definition: ParseOptions.hpp:92
optional
ostream
string