ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
Variant.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2025 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#pragma once
21
22#include "None.hpp"
23
24#include <utils/Vector.hpp>
28
29#include <boost/serialization/access.hpp>
30#include <boost/serialization/serialization.hpp>
31#include <boost/serialization/string.hpp>
32#include <boost/serialization/vector.hpp>
33
34#include <cstddef>
35#include <filesystem>
36#include <memory>
37#include <string>
38#include <type_traits>
39#include <unordered_map>
40#include <variant>
41#include <vector>
42
46
47namespace ScriptInterface {
48namespace impl {
49
50template <class... Ts> struct recursive_variant;
51
52/**
53 * @brief Helper class to inject STL containers in a recursive variant typelist.
54 * CRTP helper class that defines a base class for @ref recursive_variant,
55 * such that the `using BaseClass = detail::recursive_variant_base<Ts...>`
56 * syntax can be used in the derived class instead of writing the entire
57 * typelist again. These STL containers are used to introduce recursion.
58 */
59template <class... Ts>
61 std::variant<Ts..., std::vector<recursive_variant<Ts...>>,
62 std::unordered_map<int, recursive_variant<Ts...>>,
63 std::unordered_map<std::string, recursive_variant<Ts...>>>;
64
65/**
66 * @brief Recursive variant implementation.
67 *
68 * This boilerplate code is required to emulate the following Boost feature:
69 * @code{.cpp}
70 * using Variant = boost::make_recursive_variant<
71 * int, double, std::string, std::vector<boost::recursive_variant_>,
72 * std::unordered_map<std::string, boost::recursive_variant_>>::type;
73 * @endcode
74 * C++ doesn't natively supports the kind of reflections needed to implement
75 * this behavior. Our implementation splits the definition in two classes:
76 * a forward-declared @ref recursive_variant template class whose type
77 * parameters are "basic" types (i.e. non-recursive types), and a helper
78 * class @c recursive_variant_add_containers that injects carefully chosen
79 * STL containers into the type list. Since STL containers store a pointer
80 * to a buffer holding variant instances, the variant size doesn't need to be
81 * known at the time the variant is defined, and the variant is recursive.
82 */
83template <class... Ts>
86 using BaseClass::BaseClass;
87
88 /** @brief Is a given type part of this variant's type list. */
89 template <class T> using has_type = std::disjunction<std::is_same<T, Ts>...>;
90
91private:
93
94 template <typename Archive>
95 void serialize(Archive &ar, unsigned const /*version*/) {
96 BaseClass &self = *this;
97 ar & self;
98 }
99};
100
101} // namespace impl
102
103/**
104 * @brief Helper typedef to generate consistent variant types.
105 *
106 * This is a custom recursive variant type designed specifically for the script
107 * interface. It features all basic types required to interface with the core.
108 * Recursive types are added by @ref impl::recursive_variant_add_containers.
109 * The template parameter @c ObjectType is used to ensure instantiations like
110 * @ref Variant and @ref PackedVariant hold the same types in the same order.
111 *
112 * @tparam ObjectType Type of the script interface object handle or reference.
113 */
114template <typename ObjectType>
116 None, bool, int, std::size_t, double, std::string, std::filesystem::path,
118 Utils::Vector3d, Utils::Vector4d, std::vector<int>, std::vector<double>>;
119
120class ObjectHandle;
121using ObjectRef = std::shared_ptr<ObjectHandle>;
122
123/**
124 * @brief None-"literal".
125 */
126constexpr const None none{};
127
128/**
129 * @brief Possible types for parameters.
130 */
132
133using VariantMap = std::unordered_map<std::string, Variant>;
134
135/**
136 * @brief Make a Variant from argument.
137 *
138 * This is a convenience function, so that rather involved constructors from
139 * @ref Variant are not needed in the script interface.
140 */
141template <typename T> Variant make_variant(const T &x) { return Variant(x); }
142
143template <typename K, typename V>
144auto make_unordered_map_of_variants(std::unordered_map<K, V> const &v) {
145 return std::unordered_map<K, Variant>{v.begin(), v.end()};
146}
147
148template <typename T> auto make_vector_of_variants(std::vector<T> const &v) {
149 return std::vector<Variant>{v.begin(), v.end()};
150}
151
152/**
153 * @brief Check is a Variant holds a specific type.
154 *
155 * @tparam T type to check for
156 * @param v Variant to check in
157 * @return true, if v holds a T.
158 */
159template <class T> constexpr bool is_type(Variant const &v) {
160 return std::holds_alternative<T>(v);
161}
162
163constexpr bool is_none(Variant const &v) { return is_type<None>(v); }
164} // namespace ScriptInterface
Vector implementation and trait types for boost qvm interoperability.
Type to indicate no value in Variant.
Definition None.hpp:32
Base class for interface handles.
std::variant< Ts..., std::vector< recursive_variant< Ts... > >, std::unordered_map< int, recursive_variant< Ts... > >, std::unordered_map< std::string, recursive_variant< Ts... > > > recursive_variant_add_containers
Helper class to inject STL containers in a recursive variant typelist.
Definition Variant.hpp:63
constexpr bool is_none(Variant const &v)
Definition Variant.hpp:163
constexpr bool is_type(Variant const &v)
Check is a Variant holds a specific type.
Definition Variant.hpp:159
std::shared_ptr< ObjectHandle > ObjectRef
Definition Variant.hpp:121
T get_value(Variant const &v)
Extract value of specific type T from a Variant.
std::unordered_map< std::string, Variant > VariantMap
Definition Variant.hpp:133
auto make_unordered_map_of_variants(std::unordered_map< K, V > const &v)
Definition Variant.hpp:144
Variant make_variant(const T &x)
Make a Variant from argument.
Definition Variant.hpp:141
auto make_vector_of_variants(std::vector< T > const &v)
Definition Variant.hpp:148
make_recursive_variant< ObjectRef > Variant
Possible types for parameters.
Definition Variant.hpp:131
constexpr const None none
None-"literal".
Definition Variant.hpp:126
Utils::Vector< bool, 3 > Vector3b
Definition Variant.hpp:44
VectorXd< 3 > Vector3d
Definition Vector.hpp:185
VectorXd< 2 > Vector2d
Definition Vector.hpp:184
VectorXi< 3 > Vector3i
Definition Vector.hpp:194
VectorXd< 4 > Vector4d
Definition Vector.hpp:186
Recursive variant implementation.
Definition Variant.hpp:84
recursive_variant_add_containers< Ts... > BaseClass
Definition Variant.hpp:85
friend class boost::serialization::access
Definition Variant.hpp:92
std::disjunction< std::is_same< T, Ts >... > has_type
Is a given type part of this variant's type list.
Definition Variant.hpp:89