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