SpECTRE Documentation Coverage Report
Current view: top level - Options - Auto.hpp Hit Total Coverage
Commit: 37c384043430860f87787999aa7399d01bb3d213 Lines: 5 19 26.3 %
Date: 2024-04-20 02:24:02
Legend: Lines: hit not hit

          Line data    Source code
       1           0 : // 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             : #include <variant>
      11             : 
      12             : #include "Options/Options.hpp"
      13             : #include "Options/ParseOptions.hpp"
      14             : #include "Utilities/GetOutput.hpp"
      15             : #include "Utilities/PrettyType.hpp"
      16             : 
      17             : namespace Options {
      18             : /// The label representing the absence of a value for `Options::Auto`
      19           1 : namespace AutoLabel {
      20             : /// 'Auto' label
      21           1 : struct Auto {};
      22             : /// 'None' label
      23           1 : struct None {};
      24             : /// 'All' label
      25           1 : struct All {};
      26             : }  // namespace AutoLabel
      27             : 
      28             : /// \ingroup OptionParsingGroup
      29             : /// \brief A class indicating that a parsed value can be automatically
      30             : /// computed instead of specified.
      31             : ///
      32             : /// When an `Auto<T>` is parsed from an input file, the value may be specified
      33             : /// either as the `AutoLabel` (defaults to "Auto") or as a value of type `T`.
      34             : /// When this class is passed to the constructor of the class taking it as an
      35             : /// option, it can be implicitly converted to a `std::optional<U>`, for any
      36             : /// type `U` implicitly creatable from a `T`.
      37             : ///
      38             : /// \snippet Test_Auto.cpp example_class
      39             : /// \snippet Test_Auto.cpp example_create
      40             : template <typename T, typename Label = AutoLabel::Auto>
      41           1 : class Auto {
      42             :  public:
      43           0 :   using value_type = std::optional<T>;
      44             : 
      45           0 :   Auto() = default;
      46           0 :   explicit Auto(T value) : value_(std::move(value)) {}
      47             : 
      48             :   // These lines are just to work around a spurious warning.
      49           0 :   Auto(Auto&&) = default;
      50           0 :   Auto& operator=(Auto&&) = default;
      51             : #if defined(__GNUC__) and not defined(__clang__) and __GNUC__ >= 12 and \
      52             :     __GNUC__ < 14
      53             : #pragma GCC diagnostic push
      54             : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
      55             : #endif
      56           0 :   ~Auto() = default;
      57             : #if defined(__GNUC__) and not defined(__clang__) and __GNUC__ >= 12 and \
      58             :     __GNUC__ < 14
      59             : #pragma GCC diagnostic pop
      60             : #endif
      61             : 
      62             :   // NOLINTNEXTLINE(google-explicit-constructor)
      63             :   template <typename U>
      64             :   operator std::optional<U>() && {
      65             :     return std::move(value_);
      66             :   }
      67             : 
      68             :   // NOLINTNEXTLINE(google-explicit-constructor)
      69           0 :   operator const value_type&() const { return value_; }
      70             : 
      71             :  private:
      72           0 :   value_type value_{};
      73             : };
      74             : 
      75             : template <typename T, typename Label>
      76           0 : bool operator==(const Auto<T, Label>& a, const Auto<T, Label>& b) {
      77             :   return static_cast<const std::optional<T>&>(a) ==
      78             :          static_cast<const std::optional<T>&>(b);
      79             : }
      80             : 
      81             : template <typename T, typename Label>
      82           0 : bool operator!=(const Auto<T, Label>& a, const Auto<T, Label>& b) {
      83             :   return not(a == b);
      84             : }
      85             : 
      86             : template <typename T, typename Label>
      87           0 : std::ostream& operator<<(std::ostream& os, const Auto<T, Label>& x) {
      88             :   const std::optional<T>& value = x;
      89             :   if (value) {
      90             :     return os << get_output(*value);
      91             :   } else {
      92             :     return os << pretty_type::name<Label>();
      93             :   }
      94             : }
      95             : 
      96             : namespace Auto_detail {
      97             : template <typename Label>
      98             : struct AutoLabel {};
      99             : }  // namespace Auto_detail
     100             : 
     101             : template <typename Label>
     102             : struct create_from_yaml<Auto_detail::AutoLabel<Label>> {
     103             :   template <typename Metavariables>
     104             :   static Auto_detail::AutoLabel<Label> create(const Option& options) {
     105             :     const auto label_string = pretty_type::name<Label>();
     106             :     try {
     107             :       if (options.parse_as<std::string>() == label_string) {
     108             :         return {};
     109             :       }
     110             :     } catch (...) {
     111             :       // The node failed to parse as a string.  It is not the Label.
     112             :     }
     113             :     // The error if the std::variant parse fails will print the value
     114             :     // from the input file (and the T parse probably will too), so we
     115             :     // don't need to print it again.
     116             :     PARSE_ERROR(options.context(),
     117             :                 "Failed to parse as Auto label \"" << label_string << "\"");
     118             :   }
     119             : };
     120             : 
     121             : template <typename T, typename Label>
     122           0 : struct create_from_yaml<Auto<T, Label>> {
     123             :   template <typename Metavariables>
     124           0 :   static Auto<T, Label> create(const Option& options) {
     125             :     auto parsed_variant =
     126             :         options.parse_as<std::variant<Auto_detail::AutoLabel<Label>, T>,
     127             :                          Metavariables>();
     128             :     if (std::holds_alternative<T>(parsed_variant)) {
     129             :       return Auto<T, Label>{std::move(std::get<T>(parsed_variant))};
     130             :     } else {
     131             : #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
     132             : #pragma GCC diagnostic push
     133             : #pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
     134             : #endif  // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__
     135             :         // < 10
     136             :       return Auto<T, Label>{};
     137             : #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 8 && __GNUC__ < 10
     138             : #pragma GCC diagnostic pop
     139             : #endif  // defined(__GNUC__) && !defined(__clang__) && __GNUC__ => 8 && __GNUC__
     140             :         // < 10
     141             :     }
     142             :   }
     143             : };
     144             : }  // namespace Options

Generated by: LCOV version 1.14