Line data Source code
1 1 : // Distributed under the MIT License.
2 : // See LICENSE.txt for details.
3 :
4 : /// \file
5 : /// Defines classes and functions for making classes creatable from
6 : /// input files.
7 :
8 : #pragma once
9 :
10 : #include <memory>
11 : #include <string>
12 : #include <type_traits>
13 :
14 : #include "Options/Context.hpp"
15 : #include "Utilities/NoSuchType.hpp"
16 : #include "Utilities/TMPL.hpp"
17 : #include "Utilities/TypeTraits/IsA.hpp"
18 :
19 : /// \cond
20 : namespace YAML {
21 : class Node;
22 : } // namespace YAML
23 : /// \endcond
24 :
25 : /// Utilities for parsing input files.
26 : namespace Options {
27 : /// \ingroup OptionParsingGroup
28 : /// The type that options are passed around as. Contains YAML node
29 : /// data and an Context.
30 : ///
31 : /// \note To use any methods on this class in a concrete function you
32 : /// must include ParseOptions.hpp, but you do *not* need to include
33 : /// that header to use this in an uninstantiated
34 : /// `create_from_yaml::create` function.
35 1 : class Option {
36 : public:
37 0 : const Context& context() const;
38 :
39 : /// Append a line to the contained context.
40 1 : void append_context(const std::string& context);
41 :
42 : /// Convert to an object of type `T`.
43 : template <typename T, typename Metavariables = NoSuchType>
44 1 : T parse_as() const;
45 :
46 : /// \note This constructor overwrites the mark data in the supplied
47 : /// context with the one from the node.
48 : ///
49 : /// \warning This method is for internal use of the option parser.
50 1 : explicit Option(YAML::Node node, Context context = {});
51 :
52 : /// \warning This method is for internal use of the option parser.
53 1 : explicit Option(Context context);
54 :
55 : /// \warning This method is for internal use of the option parser.
56 1 : const YAML::Node& node() const;
57 :
58 : /// Sets the node and updates the context's mark to correspond to it.
59 : ///
60 : /// \warning This method is for internal use of the option parser.
61 1 : void set_node(YAML::Node node);
62 :
63 : private:
64 0 : std::unique_ptr<YAML::Node> node_;
65 0 : Context context_;
66 : };
67 :
68 : /// \ingroup OptionParsingGroup
69 : /// Used by the parser to create an object. The default action is to
70 : /// parse options using `T::options`. This struct may be specialized
71 : /// to change that behavior for specific types.
72 : ///
73 : /// Do not call create directly. Use Option::parse_as instead.
74 : template <typename T>
75 1 : struct create_from_yaml {
76 : template <typename Metavariables>
77 0 : static T create(const Option& options);
78 : };
79 :
80 : /// Provide multiple ways to construct a class.
81 : ///
82 : /// This type may be included in an option list along with option
83 : /// tags. When creating the class, the parser will choose one of the
84 : /// lists of options to use, depending on the user input.
85 : ///
86 : /// The class must be prepared to accept any of the possible
87 : /// alternatives as arguments to its constructor. To disambiguate
88 : /// multiple alternatives with the same types, a constructor may take
89 : /// the full list of option tags expected as its first argument.
90 : ///
91 : /// \snippet Test_Options.cpp alternatives
92 : template <typename... AlternativeLists>
93 1 : struct Alternatives {
94 : static_assert(sizeof...(AlternativeLists) >= 1,
95 : "Option alternatives must provide at least one alternative.");
96 : static_assert(
97 : tmpl::all<tmpl::list<tt::is_a<tmpl::list, AlternativeLists>...>>::value,
98 : "Option alternatives must be given as tmpl::lists.");
99 : static_assert(
100 : tmpl::none<
101 : tmpl::list<std::is_same<tmpl::list<>, AlternativeLists>...>>::value,
102 : "All option alternatives must have at least one option.");
103 : };
104 : } // namespace Options
|