Loading...
Searching...
No Matches
arg.h
Go to the documentation of this file.
1#ifndef _BBM_ARG_H_
2#define _BBM_ARG_H_
3
4#include <ostream>
6#include "util/reference.h"
7#include "util/typestring.h"
9
10
11/************************************************************************/
12/*! \file arg.h
13 \brief Structure to store an argument, with possibly a type, name and default value.
14 Refer to args.h for its usage.
15*************************************************************************/
16
17
18namespace bbm {
19
20 /**********************************************************************/
21 /*! \brief Forward declaration of bbm::arg
22
23 \tparam Type = type of the argument
24 \tparam Name = argument name
25 \tparam Default = invocable type that returns the default value
26 ***********************************************************************/
27 template<typename Type, string_literal Name, typename Default=void> struct arg;
28
29
30 /**********************************************************************/
31 /*! @{ \name type traits
32 **********************************************************************/
33 namespace detail {
34 template<typename T> struct is_arg_impl : std::false_type {};
35 template<typename T, string_literal N, typename D> struct is_arg_impl<arg<T,N,D>> : std::true_type {};
36 }
37
38 template<typename T>
39 using is_arg = bbm::detail::is_arg_impl<std::decay_t<T>>;
40
41 template<typename T>
42 inline constexpr bool is_arg_v = is_arg<T>::value;
43 //! @}
44
45
46 /**********************************************************************/
47 /*! \brief Untyped Argument (only a name)
48
49 The assignment operator is overriden to return a typed argument with the
50 same name but with a type assigned.
51 ***********************************************************************/
52 template<string_literal Name>
53 struct arg<void, Name, void>
54 {
55 static constexpr string_literal name = Name;
56 using type = void;
57
58 //! \brief Assignment of non-rvalue
59 template<typename Type> requires (!std::is_rvalue_reference_v<Type&&>)
60 inline constexpr decltype(auto) operator=(Type&& val)
61 {
62 return arg<Type, Name, void>(std::forward<Type>(val));
63 }
64
65 //! \brief Assignment of rvalue
66 template<typename Type> requires std::is_rvalue_reference_v<Type&&>
67 inline constexpr decltype(auto) operator=(Type&& val)
68 {
69 using rtype = std::add_lvalue_reference_t<std::add_const_t<Type>>;
70 return arg<rtype, Name, void>(std::forward<Type>(val));
71 }
72 };
73
74
75 /**********************************************************************/
76 /*! brief Non-reference Typed Argument without Default Value
77 **********************************************************************/
78 template<typename Type, string_literal Name> requires (!std::is_void_v<Type> && !std::is_reference_v<Type>)
80 {
81 template<typename T, string_literal N, typename D> friend struct arg;
82 static constexpr string_literal name = Name;
83 using type = Type;
84
85 //! @{ \name Constructors
86 inline constexpr arg(void) = delete;
87 inline constexpr arg(const std::decay_t<type>& val) : _value(val) {};
88
89 template<typename OtherType, string_literal OtherName, typename OtherDefault> requires std::constructible_from<std::decay_t<type>, OtherType>
90 inline constexpr arg(const arg<OtherType, OtherName, OtherDefault>& src) : arg(src._value) {}
91 //! @}
92
93 //! \brief Assignment
94 inline constexpr arg& operator=(const std::decay_t<type>& val) { _value = val; return *this; }
95
96 //! @{ \name Return the stored value
97 inline constexpr std::add_const_t<type>& value(void) const { return _value; }
98 inline constexpr type& value(void) { return _value; }
99 //! @}
100
101 private:
102 std::decay_t<type> _value;
103 };
104
105
106 /**********************************************************************/
107 /*! brief Non-reference Typed Argument with Default Value
108 **********************************************************************/
109 template<typename Type, string_literal Name, typename Default> requires (!std::is_void_v<Type> && !std::is_reference_v<Type>) && std::invocable<Default>
111 {
112 template<typename T, string_literal N, typename D> friend struct arg;
113 static constexpr string_literal name = Name;
114 using type = Type;
115
116 //! @{ \name Constructors
117 inline constexpr arg(void) : _value( Default()() ) {};
118 inline constexpr arg(const std::decay_t<type>& val) : _value(val) {}
119
120 template<typename OtherType, string_literal OtherName, typename OtherDefault> requires std::constructible_from<std::decay_t<type>, OtherType>
121 inline constexpr arg(const arg<OtherType, OtherName, OtherDefault>& src) : arg(src._value) {}
122 //! @}
123
124 //! \brief Assignment
125 inline constexpr arg& operator=(const std::decay_t<type>& val) { _value = val; return *this; }
126
127 //! @{ \name Return the stored value
128 inline constexpr std::add_const_t<type>& value(void) const { return _value; }
129 inline constexpr type& value(void) { return _value; }
130 //! @}
131
132 private:
133 std::decay_t<type> _value;
134 };
135
136
137 /**********************************************************************/
138 /*! brief Reference Typed Argument without Default Value
139
140 Assignment operator reassign the reference, not the value!
141 **********************************************************************/
142 template<typename Type, string_literal Name> requires (!std::is_void_v<Type> && std::is_reference_v<Type>)
144 {
145 template<typename T, string_literal N, typename D> friend struct arg;
146 static constexpr string_literal name = Name;
147 using type = Type;
148
149 //! @{ \name Constructors
150 inline constexpr arg(void) = delete;
151 template<typename OtherType, string_literal OtherName, typename OtherDefault> requires std::constructible_from<bbm::persistent_reference<type>, OtherType>
152 inline constexpr arg(const arg<OtherType, OtherName, OtherDefault>& src) : _value(src._value) {}
153
154 template<typename T> requires (!is_arg_v<T> && std::constructible_from<bbm::persistent_reference<type>, T&&>)
155 inline constexpr arg(T&& val) : _value(std::forward<T>(val)) {};
156 //! @}
157
158 //! \brief Assignment
159 template<typename T>
160 inline constexpr arg& operator=(T&& src)
161 {
162 _value.reassign( std::forward<T>(src) );
163 return *this;
164 }
165
166 //! @{ \name Return the stored value
167 inline constexpr type value(void) const { return _value; }
168 inline constexpr type value(void) { return _value; }
169 //! @}
170
171 private:
173 };
174
175
176 /**********************************************************************/
177 /*! brief Reference Typed Argument with Default Value
178
179 Assignment operator reassign the reference, not the value!
180 **********************************************************************/
181 template<typename Type, string_literal Name, typename Default> requires (!std::is_void_v<Type> && std::is_reference_v<Type>) && std::invocable<Default>
183 {
184 template<typename T, string_literal N, typename D> friend struct arg;
185 static constexpr string_literal name = Name;
186 using type = Type;
187
188 //! @{ \name Constructors
189 inline constexpr arg(void) : _value( Default()() ) {}
190
191 template<typename OtherType, string_literal OtherName, typename OtherDefault> requires std::constructible_from<bbm::persistent_reference<type>, OtherType>
192 inline constexpr arg(const arg<OtherType, OtherName, OtherDefault>& a) : _value(a._value) {}
193
194 template<typename T> requires (!is_arg_v<T> && std::constructible_from<bbm::persistent_reference<type>, T&&>)
195 inline constexpr arg(T&& val) : _value(std::forward<T>(val)) {}
196 //! @}
197
198 //! \brief Assignment
199 template<typename T>
200 inline constexpr arg& operator=(T&& src)
201 {
202 _value.reassign( std::forward<T>(src) );
203 return *this;
204 }
205
206 //! @{ \name Return the stored value
207 inline constexpr type value(void) const { return _value; }
208 inline constexpr type value(void) { return _value; }
209 //! @}
210
211 private:
213 };
214
215
216 /**********************************************************************/
217 /*! \brief Print bbm::arg
218 **********************************************************************/
219 template<typename T, bbm::string_literal N, typename D>
220 std::ostream& operator<<(std::ostream& s, const bbm::arg<T,N,D>& arg)
221 {
222 // print type
223 if constexpr (!std::is_void_v<T>)
224 {
225 s << bbm::typestring<T>;
226 if constexpr (!N.empty)
227 s << " ";
228 }
229
230 // print name
231 if constexpr (!N.empty)
232 s << N;
233
234 // print value
235 if constexpr (!std::is_void_v<T>)
236 s << " = " << bbm::toString(arg.value());
237
238 // print default
239 if constexpr (!std::is_void_v<D>)
240 s << " [ = " << bbm::toString(D()()) << "]";
241
242 return s;
243 }
244
245 /**********************************************************************/
246 /*! \brief arg literal
247 **********************************************************************/
248 template<string_literal NAME>
249 arg<void,NAME> operator""_arg(void)
250 {
251 return arg<void, NAME>{};
252 }
253
254} // end bbm namespace
255
256/************************************************************************/
257/*! \brief Helper Macro for creating the type of a lambda that returns a value
258*************************************************************************/
259#define ArgDef(value) decltype([](){return value; })
260
261#endif /* _BBM_ARG_H_ */
concept to check if a type has a valid string_converter.
Definition: aggregatebsdf.h:29
constexpr bool is_arg_v
Definition: arg.h:42
std::ostream & operator<<(std::ostream &s, const BSDF &bsdf)
Definition: bsdf_base.h:138
std::string toString(const T &)
toString alias
Definition: stringconvert.h:594
bbm::detail::is_arg_impl< std::decay_t< T > > is_arg
Definition: arg.h:39
Forward declaration of bbm::arg.
Definition: arg.h:27
Declaration of persistent_reference specialized below.
Definition: reference.h:100
Assignable reference with wrapper support for rvalues.
constexpr arg & operator=(T &&src)
Assignment.
Definition: arg.h:200
constexpr std::add_const_t< type > & value(void) const
Definition: arg.h:128
constexpr arg(const std::decay_t< type > &val)
Definition: arg.h:118
constexpr arg & operator=(const std::decay_t< type > &val)
Assignment.
Definition: arg.h:125
constexpr type value(void)
Definition: arg.h:208
constexpr type value(void) const
Definition: arg.h:207
constexpr arg(void)
Definition: arg.h:189
constexpr arg(const arg< OtherType, OtherName, OtherDefault > &a)
Definition: arg.h:192
constexpr arg(T &&val)
Definition: arg.h:195
Type type
Definition: arg.h:114
constexpr type & value(void)
Definition: arg.h:129
constexpr arg(const arg< OtherType, OtherName, OtherDefault > &src)
Definition: arg.h:121
bbm::persistent_reference< type > _value
Definition: arg.h:212
constexpr arg(void)
Definition: arg.h:117
std::decay_t< type > _value
Definition: arg.h:133
constexpr arg & operator=(T &&src)
Assignment.
Definition: arg.h:160
constexpr std::add_const_t< type > & value(void) const
Definition: arg.h:97
constexpr arg(const std::decay_t< type > &val)
Definition: arg.h:87
constexpr arg & operator=(const std::decay_t< type > &val)
Assignment.
Definition: arg.h:94
constexpr type value(void)
Definition: arg.h:168
constexpr type value(void) const
Definition: arg.h:167
constexpr arg(const arg< OtherType, OtherName, OtherDefault > &src)
Definition: arg.h:152
constexpr arg(void)=delete
constexpr arg(T &&val)
Definition: arg.h:155
Type type
Definition: arg.h:83
constexpr type & value(void)
Definition: arg.h:98
constexpr arg(const arg< OtherType, OtherName, OtherDefault > &src)
Definition: arg.h:90
bbm::persistent_reference< type > _value
Definition: arg.h:172
std::decay_t< type > _value
Definition: arg.h:102
void type
Definition: arg.h:56
constexpr decltype(auto) operator=(Type &&val)
Assignment of non-rvalue.
Definition: arg.h:60
Definition: string_literal.h:16
produce stringview of type name of a type. Avoids using typeid for GCC, MSVC, and CLANG....