Loading...
Searching...
No Matches
constructor.h
Go to the documentation of this file.
1#ifndef _BBM_CONSTRUCTOR_H_
2#define _BBM_CONSTRUCTOR_H_
3
5
6#include "util/type_traits.h"
7#include "util/reflection.h"
8
9#include "core/args.h"
10
11
12/************************************************************************/
13/*! \file constructor.h
14 \brief Tools for easy creation of a constructors
15
16 Case 1: a constructor that initializes all class attributes (requires bbm::refletion::attribute<T>)
17
18 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
19 BBM_DEFAULT_CONSTRUCTOR(foo)
20 {
21 // ...body...
22 }
23 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
24
25 where 'foo' is the class name, and body is a custom constructor body
26 executed after Attributes have been declared. The
27 constructor uses bbm::args to pass the arguments.
28
29 Case 2: declare a constructor that takes a list of bbm::arg
30
31 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
32 BBM_CONSTRUCTOR(foo, args, ...)
33 {
34 // ...body...
35 }
36 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37
38 where 'foo' is again the class name, 'args' is the name given to the
39 bbm::args passed as constructor arguments, followed by a list of bbm::arg
40 (or a single bbm::args).
41
42
43*************************************************************************/
44namespace bbm {
45
46 /*** Implementation detals of attribute_tuple_to_args_t ***/
47 namespace detail {
48
49 /*** Implementation details of converting a type and name into a bbm::arg ***/
50 template<typename T, string_literal N>
51 struct attribute_to_arg_impl // Default case
52 {
53 using type = bbm::arg<const std::decay_t<T>&, N>;
54 };
55
56 template<typename T, string_literal N> requires concepts::bsdf_attribute<T>
57 struct attribute_to_arg_impl<T,N> // T = bsdf_attribute
58 {
59 using type = bbm::arg<const typename std::decay_t<T>::type&, N, ArgDef(std::decay_t<T>::prop::default_value())>;
60 };
61
62 //! \brief Convert a type,name combination into a bbm::arg
63 template<typename T, string_literal N>
64 using attribute_to_arg = typename attribute_to_arg_impl<T,N>::type;
65
66 template<typename T> struct attribute_tuple_to_args_t;
67
68 /*** Implementation detail for converting a named tuple into a bbm::args ***/
69 template<typename... Ts, string_literal... Ns>
70 struct attribute_tuple_to_args_t< named<std::tuple<Ts...>, Ns...> >
71 {
72 using type = bbm::args<attribute_to_arg<Ts,Ns>...>;
73 };
74
75 } // end detail namespace
76
77 /**********************************************************************/
78 /*! \brief Convert an attribute_tuple_t to a bbm::args
79
80 \tparam TUP = attribute_tuple_t (named tuple)
81
82 Each attribute type and name in the named tuple is converted to an
83 bbm::arg and wrapped in a bbm::args. Each type,name combination is
84 converted according to the following policies:
85 + default: bbm::arg<const type&, name>
86 + bsdf_attribute: bbm::arg<const type&, name, bsdf_attribute::default_value>
87 Other policies can be added to 'attribute_to_arg_impl.
88 ***********************************************************************/
89 template<typename TUP> requires is_named_v<TUP>
90 using attribute_tuple_to_args_t = typename bbm::detail::attribute_tuple_to_args_t<std::decay_t<TUP>>::type;
91
92} // end bbm namespace
93
94/************************************************************************/
95/*! \brief Helper macro to define a default constructor based on Attribute reflection
96
97 \param ClassName = name of the constructor/class
98
99 Creates a constructor that initializes the reflected attributes. The
100 constructor uses bbm::args to pass the constructor arguments. The bbm::args
101 signature is stored in an accessible constructor_args_t alias.
102
103 The constructor will copy the corresponding bbm::args to the reflected
104 attributes in the constructor body.
105
106 Limitations:
107 + The constructor can only be defined __after__ the Attributes (and reflection)
108 have been declared.
109 + The declaration must be followed by a function body (constructor_post_init)
110 that is called after all Attributes have been set.
111 + All other attributes/parent classes are initialized with an trivial
112 constructor.
113
114 Example:
115 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
116 BBM_DEFAULT_CONSTRUCTOR(foo)
117 {
118 // ...body...
119 }
120 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
121**************************************************************************/
122#define BBM_DEFAULT_CONSTRUCTOR(ClassName) \
123 using constructor_args_t = bbm::attribute_tuple_to_args_t< BBM_ATTRIBUTES_T >; \
124 \
125 inline ClassName(const constructor_args_t& args) \
126 { \
127 auto const_cast_tuple = []<typename TUP, size_t... IDX>(TUP&& tup, std::index_sequence<IDX...>) \
128 { \
129 return std::forward_as_tuple( const_cast<std::decay_t<decltype(std::get<IDX>(tup))>&>( std::get<IDX>(tup) )... ); \
130 }; \
131 \
132 const_cast_tuple(bbm::reflection::attributes(*this), std::make_index_sequence<bbm::reflection::attributes_size<decltype(*this)>>{}) = args.values(); \
133 constructor_post_init(); \
134 } \
135 \
136 BBM_CONSTRUCTOR_FORWARD_ARGS(ClassName, constructor_args_t); \
137 \
138 inline void constructor_post_init(void) \
139
140
141
142/*************************************************************************/
143/*! \brief Helper macro for declaring a constructor based on a list of bbm::arg
144
145 \param ClassName = name of constructor/class
146 \param Args = name to give to bbm::args to access the arguments.
147 \param ... = lots of bbm::arg (or a defintion of a single bbm::args)
148 used to define the arguments to the constructor
149
150 Creates a constructor (with forwarding) that takes a single bbm::args as
151 input. Use BBM_IMPORT_ARGS to create aliases in the body of the constructor
152 of the passed arguments. A constructor_args_t is also created with the signature
153 of the bbm::args.
154
155 Example:
156 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~{.c}
157 BBM_CONSTRUCTOR(foo, args, bbm::arg<float, "a">, bbm::arg<float, "b">)
158 {
159 BBM_IMPORT_ARGS(args, a, b);
160 // ...body...
161 }
162 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
163
164 This example creates a constructor which is equivalent to the regular C++
165 constructor ``foo(float a, float b)``.
166**************************************************************************/
167#define BBM_CONSTRUCTOR(ClassName, Args, ...) \
168 using constructor_args_t = bbm::add_args_t<__VA_ARGS__>; \
169 \
170 BBM_CONSTRUCTOR_FORWARD_ARGS(ClassName, constructor_args_t); \
171 \
172 inline ClassName(const constructor_args_t& Args) \
173
174
175#endif /* _BBM_CONSTRUCTOR_H_ */
176
177
#define ArgDef(value)
Helper Macro for creating the type of a lambda that returns a value.
Definition: arg.h:259
Provides a more flexible argument passing to function and methods.
bsdf attribute contract
Definition: aggregatebsdf.h:29
typename bbm::detail::attribute_tuple_to_args_t< std::decay_t< TUP > >::type attribute_tuple_to_args_t
Convert an attribute_tuple_t to a bbm::args.
Definition: constructor.h:90
Forward declaration of bbm::arg.
Definition: arg.h:27
Definition: named.h:325
Forward declaration.
Definition: args.h:248
Compile-time reflection of: