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<U>`, for any
28 /// type `U` implicitly creatable from a `T`.
29 ///
30 /// \snippet Test_Auto.cpp example_class
31 /// \snippet Test_Auto.cpp example_create
32 template <typename T, AutoLabel Label = AutoLabel::Auto>
33 class Auto {
34  public:
35  Auto() = default;
36  explicit Auto(T value) noexcept : value_(std::move(value)) {}
37 
38  // NOLINTNEXTLINE(google-explicit-constructor)
39  template <typename U>
40  operator std::optional<U>() && { return std::move(value_); }
41 
42  // NOLINTNEXTLINE(google-explicit-constructor)
43  operator const std::optional<T>&() const { return value_; }
44 
45  private:
46  std::optional<T> value_{};
47 };
48 
49 template <typename T, AutoLabel Label>
50 bool operator==(const Auto<T, Label>& a, const Auto<T, Label>& b) noexcept {
51  return static_cast<const std::optional<T>&>(a) ==
52  static_cast<const std::optional<T>&>(b);
53 }
54 
55 template <typename T, AutoLabel Label>
56 bool operator!=(const Auto<T, Label>& a, const Auto<T, Label>& b) noexcept {
57  return not(a == b);
58 }
59 
60 template <typename T, AutoLabel Label>
61 std::ostream& operator<<(std::ostream& os, const Auto<T, Label>& x) noexcept {
62  const std::optional<T>& value = x;
63  if (value) {
64  return os << get_output(*value);
65  } else {
66  return os << Label;
67  }
68 }
69 
70 template <typename T, AutoLabel Label>
71 struct create_from_yaml<Auto<T, Label>> {
72  template <typename Metavariables>
73  static Auto<T, Label> create(const Option& options) {
74  try {
75  if (options.parse_as<std::string>() == get_output(Label)) {
76 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
77 #pragma GCC diagnostic push
78 #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
79 #endif // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__ < 10
80  return {};
81 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
82 #pragma GCC diagnostic pop
83 #endif // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__ < 10
84  }
85  } catch (...) {
86  // The node failed to parse as a string. It is not the AutoLabel.
87  }
88  return Auto<T, Label>{options.parse_as<T, Metavariables>()};
89  }
90 };
91 } // 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:33
Options::Option::parse_as
T parse_as() const
Convert to an object of type T.
Definition: ParseOptions.hpp:92
optional
ostream
string