ATLAS Offline Software
Toggle main menu visibility
Loading...
Searching...
No Matches
Tracking
Acts
ActsTrackReconstruction
src
detail
MeasurementContainerWithDimension.h
Go to the documentation of this file.
1
/*
2
Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
3
*/
4
#ifndef MEASUREMENTCONTAINERWITHDIMENSION_H
5
#define MEASUREMENTCONTAINERWITHDIMENSION_H
6
#include <variant>
7
#include <vector>
8
#include <sstream>
9
#include <algorithm>
10
#include <cassert>
11
12
// Helper type to associate the measurement dimension to the pointer to a measurement container
13
template
<
typename
container_t, std::
size_t
DIM>
14
struct
ContainerRefWithDim
{
15
public
:
16
using
container_type
= container_t;
17
ContainerRefWithDim
() :
m_container
(nullptr) {}
18
ContainerRefWithDim
(
const
container_t &
container
) :
m_container
(&
container
) {}
19
static
constexpr
std::size_t
s_dimension
= DIM;
20
// the dimension of the measurements stored in this container
21
static
constexpr
std::size_t
dimension
() {
return
s_dimension
; }
22
23
// pointer to the container
24
const
container_t *
containerPtr
()
const
{
return
m_container
; }
25
const
container_t &
container
()
const
{
return
*
m_container
; }
26
private
:
27
const
container_t *
m_container
;
28
};
29
30
#ifdef ENABLE_DEBUG_TRACE
31
#define DEBUG_TRACE(a) do { a; } while (0)
32
#else
33
#define DEBUG_TRACE(a) do { } while (0)
34
#endif
35
36
// Variant which allows to store pointer to different measurement containers with associated dimension
37
// T_Container should be of type ContainerRefWithDim< ContainerType, N>
38
// T_Container should:
39
// - implement the static constexpr T_Container::dimension()
40
// - define the alias T_Container::container_type
41
template
<
typename
derived_t,
typename
...T_Container>
42
class
MeasurementContainerWithDimension
{
43
public
:
44
using
measurement_container_variant_t
= std::variant< T_Container...>;
45
46
protected
:
47
48
const
derived_t &
derived
()
const
{
return
*
static_cast<
const
derived_t *
>
(
this
); }
49
50
template
<
typename
T>
51
static
constexpr
T
lvalue
(T &&
a
) {
return
a
;}
52
53
template
<std::
size_t
N=std::variant_size_v< measurement_container_variant_t > >
54
static
constexpr
std::size_t
dimMax
(std::size_t max_dim=0ul) {
55
if
constexpr
(N>0) {
56
using
this_variant_type =
decltype
(
lvalue
(std::get<N-1>(
measurement_container_variant_t
{}) ) );
57
return
dimMax
<N-1>(std::max( this_variant_type::dimension(), max_dim ) );
58
}
59
return
max_dim;
60
}
61
62
template
<
typename
container_t, std::
size_t
N>
63
static
constexpr
bool
isSameContainer
() {
64
using
this_variant_type =
decltype
(
lvalue
(std::get<N>(
measurement_container_variant_t
{}) ) );
65
return
std::is_same<container_t, typename this_variant_type::container_type>::value;
66
}
67
68
// helper to check whether the measurement variant contains a certain container
69
template
<
typename
container_t, std::
size_t
N= std::variant_size_v< measurement_container_variant_t > >
70
static
constexpr
unsigned
int
countVariants
() {
71
if
constexpr
(N==0) {
72
return
0;
73
}
74
else
{
75
return
countVariants
<container_t, N-1>()+
isSameContainer<container_t, N-1>
();
76
}
77
}
78
template
<
typename
container_t, std::
size_t
N= std::variant_size_v< measurement_container_variant_t > >
79
static
unsigned
int
countDerivedVariants
(
const
container_t &
a
) {
80
if
constexpr
(N==0) {
81
return
0;
82
}
83
else
{
84
if
constexpr
(
isSameContainer
<container_t, N-1>()) {
85
return
countDerivedVariants
<container_t, N-1>(
a
)+1;
86
}
87
else
{
88
using
this_variant_type =
decltype
(
lvalue
(std::get<N-1>(
measurement_container_variant_t
{}) ) );
89
using
this_container_type =
typename
this_variant_type::container_type;
90
if
constexpr
(std::is_base_of_v<container_t, this_container_type>
91
&& std::has_virtual_destructor_v<this_container_type> && std::has_virtual_destructor_v<container_t>) {
92
return
countDerivedVariants
<container_t, N-1>(
a
)+ (
dynamic_cast<
const
this_container_type *
>
(&
a
) !=
nullptr
);
93
}
94
else
{
95
return
countDerivedVariants
<container_t, N-1>(
a
);
96
}
97
}
98
}
99
}
100
protected
:
101
template
<std::
size_t
N= std::variant_size_v< measurement_container_variant_t > >
102
static
void
dumpVariantTypesImpl
(std::ostream &out) {
103
if
constexpr
(N>0) {
104
using
a_type =
decltype
(
lvalue
(std::get<N-1>(
measurement_container_variant_t
{}) ) );
105
out << N-1 <<
": "
<<
typeid
(a_type).name() << std::endl;
106
dumpVariantTypesImpl
<N-1>(out);
107
}
108
}
109
static
void
throwContainerNotInVariant
(
const
char
*
a
) {
110
std::stringstream
msg
;
111
msg
<<
"Container "
<<
a
<<
" not in variant:"
<< std::endl;
112
dumpVariantTypesImpl
(
msg
);
113
throw
std::runtime_error(
msg
.str());
114
}
115
116
template
<
typename
container_t,
bool
check_dimension, std::
size_t
N >
117
static
measurement_container_variant_t
getContainerWithDimensionNoAmbiguities
(
const
container_t &
a
,
unsigned
int
dimension=0) {
118
if
constexpr
(N==0) {
119
// this measns that the container_t has not been found in the list of possible options of the variant
120
// reasons: the type is not in the list, a derived type was provided and compaibility was not understood
121
throwContainerNotInVariant
(
typeid
(
a
).name());
122
using
this_variant_type =
decltype
(
lvalue
(std::get<0>(
measurement_container_variant_t
{}) ) );
123
return
this_variant_type();
124
}
125
else
{
126
using
this_variant_type =
decltype
(
lvalue
(std::get<N-1>(
measurement_container_variant_t
{}) ) );
127
using
this_container_type =
typename
this_variant_type::container_type ;
128
DEBUG_TRACE
( std::cout <<
"DEBUG search option for "
<<
typeid
(container_t).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
129
<<
" option: "
<< N <<
" "
<<
typeid
(this_container_type).name() <<
" dim "
<< this_variant_type::dimension()
130
<<
" check dimension ? "
<< check_dimension <<
" desired dimension "
<< dimension
131
<< std:: endl );
132
if
constexpr
(std::is_same_v<this_container_type, container_t>) {
133
// this option of the variant has perfect type match.
134
if
constexpr
(!check_dimension &&
countVariants<container_t>
()==1) {
135
// if dimensions are not to be checked there must not be other options which also match the type
136
// the caller should have ensureed that this branch is impossible,
137
// but this can only be excluded at runtime, so a static_assert
138
// is impossible here
139
assert( (
countVariants<this_container_type,N-1>
()) == 0 );
140
DEBUG_TRACE
( std::cout <<
"DEBUG --> for "
<<
typeid
(container_t).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
141
<<
" foumd unambiguous option: "
<< N <<
" "
<<
typeid
(this_container_type).name() <<
" dim "
<< this_variant_type::dimension()
142
<< std:: endl );
143
return
ContainerRefWithDim<container_t, this_variant_type::dimension()>
(
a
);
144
}
145
else
{
146
// otherwise check if the dimension of this option is identical to the
147
// expected dimension
148
if
(this_variant_type::dimension() == dimension) {
149
DEBUG_TRACE
( std::cout <<
"DEBUG --> for "
<<
typeid
(container_t).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
150
<<
" foumd dimension option: "
<< N <<
" "
<<
typeid
(this_container_type).name() <<
" dim "
<< this_variant_type::dimension()
151
<< std:: endl );
152
return
ContainerRefWithDim<container_t, this_variant_type::dimension()>
(
a
);
153
}
154
}
155
}
156
else
if
constexpr
(std::is_base_of_v<container_t, this_container_type>) {
157
// it is also possible that the container is a base of an option of the variant.
158
if
constexpr
(std::has_virtual_destructor_v<this_container_type> && std::has_virtual_destructor_v<container_t>) {
159
// casting can only be done safely if dynamic casts are possible, which requires
160
// a virtuaal destructor
161
const
this_container_type *derived_container =
dynamic_cast<
const
this_container_type *
>
(&
a
);
162
if
(derived_container) {
163
// if the provided container can be casted to the type of this variant option
164
// then check the dimensions
165
if
constexpr
(!check_dimension) {
166
// Branch may be incorrectly chose and/or assert may fail
167
// if A is base of B and B is Base of C and both B and C are options of the variant
168
// the auto-detection will treat B
169
if
constexpr
(
countVariants
<container_t,N-1>() != 0) {
170
return
getContainerWithDimensionNoAmbiguities
<container_t, check_dimension, N-1>(
a
, dimension);
171
}
172
else
{
173
DEBUG_TRACE
( std::cout <<
"DEBUG --> for "
<<
typeid
(this_container_type).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
174
<<
" foumd derived option: "
<< N <<
" "
<<
typeid
(this_container_type).name() <<
" dim "
<< this_variant_type::dimension()
175
<< std:: endl );
176
return
ContainerRefWithDim<this_container_type, this_variant_type::dimension()>
(*derived_container);
177
}
178
}
179
else
{
180
if
(this_variant_type::dimension() == dimension) {
181
DEBUG_TRACE
( std::cout <<
"DEBUG --> for "
<<
typeid
(this_container_type).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
182
<<
" derived with dimension option: "
<< N <<
" "
<<
typeid
(this_container_type).name()
183
<<
" dim "
<< this_variant_type::dimension()
184
<< std:: endl );
185
return
ContainerRefWithDim<this_container_type, this_variant_type::dimension()>
(*derived_container);
186
}
187
}
188
}
189
}
190
}
191
return
getContainerWithDimensionNoAmbiguities
<container_t, check_dimension, N-1>(
a
, dimension);
192
}
193
}
194
195
template
<
typename
container_t, std::
size_t
N>
196
static
unsigned
int
getDimensionOfDerivedVariantOption
(
const
container_t &
a
) {
197
if
constexpr
(N==0) {
198
// failure
199
return
0;
200
}
201
else
{
202
using
this_variant_type =
decltype
(
lvalue
(std::get<N-1>(
measurement_container_variant_t
{}) ) );
203
using
this_container_type =
typename
this_variant_type::container_type;
204
205
DEBUG_TRACE
( std::cout <<
"DEBUG determin dimension for "
<<
typeid
(container_t).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
206
<<
" option: "
<< N <<
" "
<<
typeid
(this_container_type).name() <<
" dim "
<< this_variant_type::dimension()
207
<< std:: endl );
208
209
if
constexpr
(std::is_same<container_t, this_container_type>::value) {
210
DEBUG_TRACE
( std::cout <<
"DEBUG get dimension for "
<<
typeid
(container_t).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
211
<<
" option: "
<< N <<
" "
<<
typeid
(this_container_type).name() <<
" dim "
<< this_variant_type::dimension()
212
<< std:: endl );
213
return
derived_t::getDimension(
a
);
214
}
215
else
if
constexpr
(std::is_base_of_v<container_t, this_container_type>) {
216
DEBUG_TRACE
( std::cout <<
"DEBUG try get dimension for derived "
<<
typeid
(container_t).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
217
<<
" option: "
<< N <<
" "
<<
typeid
(this_container_type).name() <<
" dim "
<< this_variant_type::dimension()
218
<< std:: endl );
219
// it is also possible that the container is a base of an option of the variant.
220
if
constexpr
(std::has_virtual_destructor_v<this_container_type> && std::has_virtual_destructor_v<container_t>) {
221
// if there is no ambiguity there is no point in determining the dimension
222
// @TODO but this does not guarantee that this option matches if the provided container
223
// can have multiple dimensions.
224
if
constexpr
(
countVariants<this_container_type>
() > 1) {
225
// casting can only be done safely if dynamic casts are possible, which requires
226
// a virtual destructor
227
const
this_container_type *derived_container =
dynamic_cast<
const
this_container_type *
>
(&
a
);
228
if
(derived_container) {
229
return
derived_t::getDimension(*derived_container);
230
}
231
}
232
}
233
}
234
return
getDimensionOfDerivedVariantOption
<container_t, N-1>(
a
);
235
}
236
}
237
238
template
<
typename
container_t, std::
size_t
= std::variant_size_v< measurement_container_variant_t > >
239
static
measurement_container_variant_t
getContainerWithDimension
(
const
container_t &
a
) {
240
constexpr
unsigned
int
variant_multiplicity =
countVariants<container_t>
();
241
// the container must by among the options of the measurement_container_variant_t
242
static
constexpr
std::size_t NVariants = std::variant_size_v< measurement_container_variant_t >;
243
if
constexpr
( variant_multiplicity == 1) {
244
return
getContainerWithDimensionNoAmbiguities<container_t, false, NVariants>
(
a
);
245
}
246
else
{
247
if
(variant_multiplicity==0) {
248
if
(
countDerivedVariants<container_t>
(
a
) == 1) {
249
return
getContainerWithDimensionNoAmbiguities<container_t, false, NVariants>
(
a
);
250
}
251
}
252
DEBUG_TRACE
( std::cout <<
"DEBUG need to search with dimension check for "
<<
typeid
(container_t).name() <<
" (aka "
<<
typeid
(
a
).name() <<
")"
253
<<
" multiplicity : "
<< variant_multiplicity <<
" derived "
<<
countDerivedVariants<container_t>
(
a
)
254
<< std:: endl );
255
return
getContainerWithDimensionNoAmbiguities<container_t, true, NVariants>
(
a
,
getDimensionOfDerivedVariantOption<container_t,NVariants>
(
a
));
256
}
257
}
258
};
259
260
template
<
typename
derived_t,
typename
... T_Container>
261
class
MeasurementContainerListWithDimension
:
protected
MeasurementContainerWithDimension
<derived_t, T_Container...> {
262
public
:
263
using
Base
=
MeasurementContainerWithDimension
<derived_t,T_Container...>;
264
using
measurement_container_variant_t
=
Base::measurement_container_variant_t
;
265
private
:
266
std::vector< measurement_container_variant_t >
m_containerList
;
267
268
public
:
269
static
constexpr
std::size_t
getMeasurementDimMax
() {
270
return
Base::dimMax
();
271
}
272
static
void
dumpVariantTypes
(std::ostream &out) {
273
Base::template
dumpVariantTypesImpl<>
(out);
274
}
275
276
std::size_t
size
()
const
{
277
return
m_containerList
.size();
278
}
279
280
const
measurement_container_variant_t
&
at
(std::size_t container_index)
const
{
281
return
m_containerList
.at(container_index);
282
}
283
const
std::vector< measurement_container_variant_t > &
containerList
()
const
{
return
m_containerList
;}
284
285
template
<
typename
container_t>
286
void
setContainer
(std::size_t container_index,
const
container_t &container) {
287
if
(container_index>=
m_containerList
.size()) {
288
m_containerList
.resize(container_index+1);
289
}
290
m_containerList
[container_index] = this->
getContainerWithDimension
(container);
291
if
( std::holds_alternative<
decltype
(this->
lvalue
(
get<0>
(
measurement_container_variant_t
{}))) >(
m_containerList
[container_index])
292
&& std::get<0>(
m_containerList
[container_index]).containerPtr() ==
nullptr
) {
293
// @TODO should never happen
294
std::runtime_error(
"Unhandled measurement type"
);
295
}
296
297
}
298
299
};
300
#endif
a
static Double_t a
Definition
LArPhysWaveHECTool.cxx:38
DEBUG_TRACE
#define DEBUG_TRACE(a)
Definition
MeasurementContainerWithDimension.h:33
MeasurementContainerListWithDimension
Definition
MeasurementContainerWithDimension.h:261
MeasurementContainerListWithDimension::measurement_container_variant_t
Base::measurement_container_variant_t measurement_container_variant_t
Definition
MeasurementContainerWithDimension.h:264
MeasurementContainerListWithDimension::at
const measurement_container_variant_t & at(std::size_t container_index) const
Definition
MeasurementContainerWithDimension.h:280
MeasurementContainerListWithDimension::getMeasurementDimMax
static constexpr std::size_t getMeasurementDimMax()
Definition
MeasurementContainerWithDimension.h:269
MeasurementContainerListWithDimension::setContainer
void setContainer(std::size_t container_index, const container_t &container)
Definition
MeasurementContainerWithDimension.h:286
MeasurementContainerListWithDimension::size
std::size_t size() const
Definition
MeasurementContainerWithDimension.h:276
MeasurementContainerListWithDimension::containerList
const std::vector< measurement_container_variant_t > & containerList() const
Definition
MeasurementContainerWithDimension.h:283
MeasurementContainerListWithDimension::m_containerList
std::vector< measurement_container_variant_t > m_containerList
Definition
MeasurementContainerWithDimension.h:266
MeasurementContainerListWithDimension::dumpVariantTypes
static void dumpVariantTypes(std::ostream &out)
Definition
MeasurementContainerWithDimension.h:272
MeasurementContainerListWithDimension::Base
MeasurementContainerWithDimension< derived_t, T_Container... > Base
Definition
MeasurementContainerWithDimension.h:263
MeasurementContainerWithDimension
Definition
MeasurementContainerWithDimension.h:42
MeasurementContainerWithDimension::throwContainerNotInVariant
static void throwContainerNotInVariant(const char *a)
Definition
MeasurementContainerWithDimension.h:109
MeasurementContainerWithDimension::dumpVariantTypesImpl
static void dumpVariantTypesImpl(std::ostream &out)
Definition
MeasurementContainerWithDimension.h:102
MeasurementContainerWithDimension::derived
const derived_t & derived() const
Definition
MeasurementContainerWithDimension.h:48
MeasurementContainerWithDimension::countDerivedVariants
static unsigned int countDerivedVariants(const container_t &a)
Definition
MeasurementContainerWithDimension.h:79
MeasurementContainerWithDimension::getDimensionOfDerivedVariantOption
static unsigned int getDimensionOfDerivedVariantOption(const container_t &a)
Definition
MeasurementContainerWithDimension.h:196
MeasurementContainerWithDimension::countVariants
static constexpr unsigned int countVariants()
Definition
MeasurementContainerWithDimension.h:70
MeasurementContainerWithDimension::getContainerWithDimensionNoAmbiguities
static measurement_container_variant_t getContainerWithDimensionNoAmbiguities(const container_t &a, unsigned int dimension=0)
Definition
MeasurementContainerWithDimension.h:117
MeasurementContainerWithDimension::isSameContainer
static constexpr bool isSameContainer()
Definition
MeasurementContainerWithDimension.h:63
MeasurementContainerWithDimension::measurement_container_variant_t
std::variant< T_Container... > measurement_container_variant_t
Definition
MeasurementContainerWithDimension.h:44
MeasurementContainerWithDimension::getContainerWithDimension
static measurement_container_variant_t getContainerWithDimension(const container_t &a)
Definition
MeasurementContainerWithDimension.h:239
MeasurementContainerWithDimension::lvalue
static constexpr T lvalue(T &&a)
Definition
MeasurementContainerWithDimension.h:51
MeasurementContainerWithDimension::dimMax
static constexpr std::size_t dimMax(std::size_t max_dim=0ul)
Definition
MeasurementContainerWithDimension.h:54
get
T * get(TKey *tobj)
get a TObject* from a TKey* (why can't a TObject be a TKey?)
Definition
hcg.cxx:132
ContainerRefWithDim
Definition
MeasurementContainerWithDimension.h:14
ContainerRefWithDim::ContainerRefWithDim
ContainerRefWithDim(const container_t &container)
Definition
MeasurementContainerWithDimension.h:18
ContainerRefWithDim::container_type
container_t container_type
Definition
MeasurementContainerWithDimension.h:16
ContainerRefWithDim::ContainerRefWithDim
ContainerRefWithDim()
Definition
MeasurementContainerWithDimension.h:17
ContainerRefWithDim::container
const container_t & container() const
Definition
MeasurementContainerWithDimension.h:25
ContainerRefWithDim::containerPtr
const container_t * containerPtr() const
Definition
MeasurementContainerWithDimension.h:24
ContainerRefWithDim::m_container
const container_t * m_container
Definition
MeasurementContainerWithDimension.h:27
ContainerRefWithDim::s_dimension
static constexpr std::size_t s_dimension
Definition
MeasurementContainerWithDimension.h:19
ContainerRefWithDim::dimension
static constexpr std::size_t dimension()
Definition
MeasurementContainerWithDimension.h:21
msg
MsgStream & msg
Definition
testRead.cxx:32
Generated on
for ATLAS Offline Software by
1.17.0