23
23
#ifndef BAR_COMPONENT_H
24
24
#define BAR_COMPONENT_H
25
25
26
+ #include < vclib/concepts/const_correctness.h>
27
+ #include < vclib/concepts/mesh/components/component.h>
26
28
#include < vclib/mesh/components/bases/component.h>
27
29
#include < vclib/types.h>
28
30
32
34
* Due to the complexity of this class, VCLib provides a vcl::Component class
33
35
* that can be used as a base class.
34
36
*
35
- * In this example, the component stores two values: an integer that can be
36
- * accessed trough the member function `foo ()`, and a double that can be
37
- * accessed trough the member function `bar ()`.
37
+ * In this example, the component stores two values: a double that can be
38
+ * accessed trough the member function `bar ()`, and a vector of uint that can be
39
+ * accessed trough the member function `barVector ()`.
38
40
*/
39
41
40
42
// a component needs a concept, that allows to test if other elements/meshes
41
43
// have the same component.
42
44
// the concept should just check if the element/mesh has the member functions
43
45
// that are part of the component class.
44
46
template <typename T>
45
- concept HasBarComponent = requires (T t, const T& ct) {
46
- // accessor to the int value of the bar component, returns int&
47
- { t.foo () } -> std::same_as<int &>;
48
-
49
- // const accessor to the int value of the bar component
50
- { ct.foo () } -> std::same_as<int >;
51
-
52
- // accessor to the double value of the bar component, returns int&
53
- { t.bar () } -> std::same_as<double &>;
54
-
55
- // const accessor to the double value of the bar component
56
- { ct.bar () } -> std::same_as<double >;
47
+ concept HasBarComponent = requires (T&& obj) {
48
+ // accessors to the bar component, for const and non-const objects
49
+ { obj.bar () } -> std::convertible_to<double >;
50
+ { obj.barVector () } -> std::convertible_to<std::vector<uint>>;
51
+
52
+ // non const requirements
53
+ requires vcl::IsConst<T> || requires {
54
+ // non-const accessors, return references
55
+ { obj.bar () } -> std::same_as<double &>;
56
+ { obj.barVector () } -> std::same_as<std::vector<uint>&>;
57
+ };
57
58
};
58
59
59
60
// if you want, you can also define a concept that checks if an element has
@@ -65,17 +66,17 @@ concept HasOptionalColor =
65
66
66
67
// define a constant uint that identifies the component (same idea used for
67
68
// COMPONENT_ID in the FooComponent)
68
- inline static const uint BAR_COMPONENT = vcl::COMPONENTS_NUMBER + 0 ;
69
+ inline static const uint BAR_COMPONENT = vcl::CompId:: COMPONENTS_NUMBER + 1 ;
69
70
70
71
namespace detail {
71
72
72
73
// we wrap all the data stored by the component in a struct.
73
- // in this case we could use also a std::pair, but it doesn't matter
74
+ // in this case we could use also a std::pair, but it doesn't matter.
74
75
// the only important thing is to have all the data wrapped in a single type
75
76
struct BarData
76
77
{
77
- int foo;
78
78
double bar;
79
+ std::vector<uint> barVector;
79
80
};
80
81
81
82
} // namespace detail
@@ -93,20 +94,26 @@ bool isBarComponentAvailableOn(const vcl::ElementOrMeshConcept auto& element);
93
94
// we called it BarComponentT because BarComponent will be aliased without
94
95
// template arguments later (and will be the horizontal component).
95
96
//
96
- // template arguments are two:
97
- // - ElementType: void if the component will be horizontal, or the type of the
98
- // Element that will have the component if vertical;
99
- // - OPTIONAL: true if the component will be optional. Will be valid only if
97
+ // template arguments are three:
98
+ // - ElementType: the type of the Element that will have the component (could
99
+ // be void if the component will always be horizontal and does not need to
100
+ // access the derived Element type)
101
+ // - VERTICAL: true if the component will be vertical. Will be valid only if
100
102
// ElementType != void
103
+ // - OPTIONAL: true if the component will be optional. Will be valid only if
104
+ // VERTICAL == true
101
105
//
102
106
// The class inherits from the vcl::comp::Component class, that has a list of
103
107
// template arguments.
104
- template <typename ElementType = void , bool OPTIONAL = false >
108
+ template <
109
+ typename ElementType = void ,
110
+ bool VERTICAL = false ,
111
+ bool OPTIONAL = false >
105
112
class BarComponentT :
106
113
public vcl::comp::Component<
107
114
108
115
// CRTP: the first argument is always the component class itself
109
- BarComponentT<ElementType, OPTIONAL>,
116
+ BarComponentT<ElementType, VERTICAL, OPTIONAL>,
110
117
111
118
// ID of the component, same used in the FooComponent, but in this
112
119
// case it is a template argument of the vcl::comp::Component class
@@ -119,16 +126,20 @@ class BarComponentT :
119
126
// Same ElementType argument of the BarComponentT class
120
127
ElementType,
121
128
129
+ // Same VERTICAL argument of the BarComponentT class
130
+ VERTICAL,
131
+
122
132
// Same OPTIONAL argument of the BarComponentT class
123
133
OPTIONAL>
124
134
{
125
135
// alias of the base vcl::comp::Component class - just for detail use
126
136
// to access the member functions of the base class
127
137
using Base = vcl::comp::Component<
128
- BarComponentT<ElementType, OPTIONAL>,
138
+ BarComponentT<ElementType, VERTICAL, OPTIONAL>,
129
139
BAR_COMPONENT,
130
140
detail::BarData,
131
141
ElementType,
142
+ VERTICAL,
132
143
OPTIONAL>;
133
144
134
145
public:
@@ -137,25 +148,28 @@ class BarComponentT :
137
148
// we access the data stored by calling Base::data(). The returned type
138
149
// is the same of the third template argument of the vcl::comp::Component
139
150
// class -- in this case, detail::BarData
140
- int & foo () { return Base::data ().foo ; }
141
-
142
- int foo () const { return Base::data ().foo ; }
143
-
144
151
double & bar () { return Base::data ().bar ; }
145
152
146
153
double bar () const { return Base::data ().bar ; }
147
154
155
+ std::vector<uint>& barVector () { return Base::data ().barVector ; }
156
+
157
+ const std::vector<uint>& barVector () const
158
+ {
159
+ return Base::data ().barVector ;
160
+ }
161
+
148
162
protected:
149
- // first requirement: a protected `importFrom` member function
163
+ // the protected `importFrom` member function
150
164
template <typename Element> // another element, maybe from another mesh type
151
165
void importFrom (const Element& e, bool = true )
152
166
{
153
167
// will import the bar component from the element e only if it also has
154
168
// the bar component
155
169
if constexpr (HasBarComponent<Element>) { // compile time check
156
170
if (isBarComponentAvailableOn (e)) { // runtime check
157
- foo () = e.foo ();
158
171
bar () = e.bar ();
172
+ barVector () = e.barVector ();
159
173
}
160
174
}
161
175
}
@@ -173,10 +187,14 @@ bool isBarComponentAvailableOn(const vcl::ElementOrMeshConcept auto& element)
173
187
using BarComponent = BarComponentT<>; // horizontal component
174
188
175
189
template <typename ElementType>
176
- using VerticalBarComponent = BarComponentT<ElementType>; // vertical component
190
+ using VerticalBarComponent = BarComponentT<ElementType, true >; // vertical
177
191
178
192
template <typename ElementType>
179
- using OptionalBarComponent = BarComponentT<ElementType, true >; // optional
193
+ using OptionalBarComponent = BarComponentT<ElementType, true , true >; // optional
194
+
195
+ static_assert (
196
+ vcl::comp::ComponentConcept<BarComponent>,
197
+ " Make sure that the BarComponent satisfies the ComponentConcept." );
180
198
181
199
static_assert (
182
200
HasBarComponent<BarComponent>,
0 commit comments