ATLAS Offline Software
Loading...
Searching...
No Matches
SystematicsHandles/SystematicsHandles/CopyHelpers.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#ifndef SYSTEMATICS_HANDLES__COPY_HELPERS_H
9#define SYSTEMATICS_HANDLES__COPY_HELPERS_H
10
20
21#include <memory>
22#include <type_traits>
23#include <utility> //std::declval
24
25namespace CP
26{
27 namespace detail
28 {
30 template <typename T>
32 {
33 template <class, class> class checker;
34
35 template <typename C>
36 static std::true_type test_iparticle(checker<C, decltype((*(const xAOD::IParticle**)nullptr) = ((C*)nullptr)->at(0))> *);
37
38 template <typename C>
39 static std::false_type test_iparticle(...);
40
41 template <typename C>
42 static std::true_type test_container(checker<C, decltype((*(const SG::AuxVectorBase**)nullptr) = ((C*)nullptr))>*);
43
44 template <typename C>
45 static std::false_type test_container(...);
46
51 static const int value = ( std::is_same< std::true_type, decltype( test_iparticle< T >( nullptr ) ) >::value ?
52 1 : ( std::is_same< std::true_type, decltype( test_container< T >( nullptr ) ) >::value ?
53 2 : 3 ) );
54 };
55
63 template<typename T, int type = ContainerType<T>::value>
65 {
66 static_assert ((type==1)||(type==2)||(type==3),
67 "Type can not be shallow copied");
68 };
69
70 template<typename T>
71 struct ShallowCopy<T,1>
72 {
74 public:
75 typedef std::decay<decltype(
76 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
77
78 static StatusCode
79 getCopy (MsgStream& msgStream, StoreType& store,
80 T*& object, const T *inputObject,
81 const std::string& outputName, const std::string& auxName)
82 {
83 // Define the msg(...) function as a lambda.
84 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
85 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
86 msgStream << lvl;
87 return msgStream;
88 };
89
90 // Make sure that we get a valid pointer.
91 assert (inputObject != nullptr);
92
93 // Handle the case when the input object is a view container.
94 if( ! inputObject->getConstStore() ) {
95
96 // Decide how to handle the container.
97 if( inputObject->size() ) {
98 // Get the pointer to the "owning container" from the first
99 // element.
100 const T* originContainer =
101 dynamic_cast< const T* >( ( *inputObject )[ 0 ]->container() );
102 if (!originContainer){
103 ANA_MSG_ERROR( "Dynamic cast failed." );
104 return StatusCode::FAILURE;
105 }
106 // Make sure that every element in the view container has the same
107 // parent.
108 for( size_t i = 1; i < inputObject->size(); ++i ) {
109 if( ( *inputObject )[ i ]->container() != originContainer ) {
110 ANA_MSG_ERROR( "Not all elements of the received view "
111 "container come from the same container!" );
112 return StatusCode::FAILURE;
113 }
114 }
115 // Postfix for the shallow-copy container of the origin container.
116 static const char* const ORIGIN_POSTFIX = "_ShallowCopyOrigin";
117 // Make a shallow copy of the origin container.
118 auto originCopy = xAOD::shallowCopyContainer( *originContainer, Gaudi::Hive::currentContext() );
119 if( ( ! originCopy.first ) || ( ! originCopy.second ) ) {
120 ANA_MSG_ERROR( "Failed to shallow copy the origin of a view "
121 << "container, meant for: " << outputName );
122 return StatusCode::FAILURE;
123 }
124 // Make a view copy on top of it.
125 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
126 auto viewCopyPtr = viewCopy.get();
127 for( const auto* element : *inputObject ) {
128 viewCopy->push_back( originCopy.first->at( element->index() ) );
129 }
130
131 // ...and record it.
132 ANA_CHECK( store.record( std::move(originCopy.first),
133 outputName + ORIGIN_POSTFIX ) );
134 ANA_CHECK( store.record( std::move(originCopy.second),
135 outputName + ORIGIN_POSTFIX + "Aux." ) );
136
137 // Set the origin links on it. Note that
138 // xAOD::setOriginalObjectLink's "container version" doesn't work
139 // with view containers, we have to call this function one-by-one
140 // on the elements.
141 for( size_t i = 0; i < inputObject->size(); ++i ) {
142 if( ! xAOD::setOriginalObjectLink( *( ( *inputObject )[ i ] ),
143 *( ( *viewCopy )[ i ] ) ) ) {
144 return StatusCode::FAILURE;
145 }
146 }
147 // Finally, record the view container with the requested name.
148 ANA_CHECK( store.record( std::move(viewCopy), outputName ) );
149 // The copy is done.
150 object = viewCopyPtr;
151 return StatusCode::SUCCESS;
152 } else {
153 // If the container was empty, then let's just make a new empty
154 // container, and that's that...
155 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
156 auto viewCopyPtr = viewCopy.get();
157 ANA_CHECK( store.record( std::move(viewCopy), outputName ) );
158 // The copy is done.
159 object = viewCopyPtr;
160 return StatusCode::SUCCESS;
161 }
162
163 } else {
164
165 // We can just copy the container as is.
166 auto copy = xAOD::shallowCopyContainer( *inputObject, Gaudi::Hive::currentContext() );
167 if (!copy.first || !copy.second)
168 {
169 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
170 ANA_MSG_ERROR ("likely shallow copying a view container");
171 return StatusCode::FAILURE;
172 }
173
174 if (!xAOD::setOriginalObjectLink (*inputObject, *copy.first)) {
175 return StatusCode::FAILURE;
176 }
177 //coverity[WRAPPER_ESCAPE]
178 object = copy.first.get();
179 ANA_CHECK (store.record (std::move(copy.second), auxName));
180 ANA_CHECK (store.record (std::move(copy.first), outputName));
181 return StatusCode::SUCCESS;
182 }
183 }
184 };
185
186 template<typename T>
187 struct ShallowCopy<T,2>
188 {
190 public:
191 typedef std::decay<decltype(
192 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
193
194 static StatusCode
195 getCopy (MsgStream& msgStream, StoreType& store,
196 T*& object, const T *inputObject,
197 const std::string& outputName, const std::string& auxName)
198 {
199 // Define the msg(...) function as a lambda.
200 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
201 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
202 msgStream << lvl;
203 return msgStream;
204 };
205
206 // Make sure that we get a valid pointer.
207 assert (inputObject != nullptr);
208
209 // Handle the case when the input object is a view container.
210 if( ! inputObject->getConstStore() ) {
211
212 // Decide how to handle the container.
213 if( inputObject->size() ) {
214 // Get the pointer to the "owning container" from the first
215 // element.
216 const T* originContainer = dynamic_cast< const T* >( ( *inputObject )[ 0 ]->container() );
217 if (!originContainer){
218 ANA_MSG_ERROR( "Dynamic cast returned nullptr!" );
219 return StatusCode::FAILURE;
220 }
221 // Make sure that every element in the view container has the same
222 // parent.
223 for( size_t i = 1; i < inputObject->size(); ++i ) {
224 if( ( *inputObject )[ i ]->container() != originContainer ) {
225 ANA_MSG_ERROR( "Not all elements of the received view "
226 "container come from the same container!" );
227 return StatusCode::FAILURE;
228 }
229 }
230 // Postfix for the shallow-copy container of the origin container.
231 static const char* const ORIGIN_POSTFIX = "_ShallowCopyOrigin";
232 // Make a shallow copy of the origin container.
233 auto originCopy = xAOD::shallowCopyContainer( *originContainer, Gaudi::Hive::currentContext() );
234 if( ( ! originCopy.first ) || ( ! originCopy.second ) ) {
235 ANA_MSG_ERROR( "Failed to shallow copy the origin of a view "
236 << "container, meant for: " << outputName );
237 return StatusCode::FAILURE;
238 }
239
240 // Make a view copy on top of it.
241 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
242 auto viewCopyPtr = viewCopy.get();
243 for( const auto* element : *inputObject ) {
244 viewCopy->push_back( originCopy.first->at( element->index() ) );
245 }
246
247 // ...and record it.
248 ANA_CHECK( store.record( std::move(originCopy.first),
249 outputName + ORIGIN_POSTFIX ) );
250 ANA_CHECK( store.record( std::move(originCopy.second),
251 outputName + ORIGIN_POSTFIX +
252 "Aux." ) );
253
254 // Finally, record the view container with the requested name.
255 ANA_CHECK( store.record( std::move(viewCopy), outputName ) );
256 // The copy is done.
257 object = viewCopyPtr;
258 return StatusCode::SUCCESS;
259 } else {
260 // If the container was empty, then let's just make a new empty
261 // container, and that's that...
262 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
263 auto viewCopyPtr = viewCopy.get();
264 ANA_CHECK( store.record( std::move(viewCopy), outputName ) );
265 // The copy is done.
266 object = viewCopyPtr;
267 return StatusCode::SUCCESS;
268 }
269
270 } else {
271
272 // We can just copy the container as is.
273 auto copy = xAOD::shallowCopyContainer( *inputObject, Gaudi::Hive::currentContext() );
274 if (!copy.first || !copy.second)
275 {
276 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
277 ANA_MSG_ERROR ("likely shallow copying a view container");
278 return StatusCode::FAILURE;
279 }
280 //coverity warns about the bare pointer outliving the 'copy' object
281 //coverity[WRAPPER_ESCAPE]
282 object = copy.first.get();
283 ANA_CHECK (store.record (std::move(copy.second), auxName));
284 ANA_CHECK (store.record (std::move(copy.first), outputName));
285 return StatusCode::SUCCESS;
286 }
287 }
288 };
289
290 template<typename T>
291 struct ShallowCopy<T,3>
292 {
294 public:
295 typedef std::decay<decltype(
296 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
297
298 static StatusCode
299 getCopy (MsgStream& msgStream, StoreType& store,
300 T*& object, const T *inputObject,
301 const std::string& outputName, const std::string& auxName)
302 {
303 // Define the msg(...) function as a lambda.
304 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
305 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
306 msgStream << lvl;
307 return msgStream;
308 };
309
310 // We can just copy the object as is.
311 auto copy = xAOD::shallowCopyObject( *inputObject, Gaudi::Hive::currentContext() );
312 if (!copy.first || !copy.second)
313 {
314 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
315 ANA_MSG_ERROR ("likely shallow copying a view container");
316 return StatusCode::FAILURE;
317 }
318 //coverity[WRAPPER_ESCAPE]
319 object = copy.first.get();
320 ANA_CHECK (store.record (std::move(copy.second), auxName));
321 ANA_CHECK (store.record (std::move(copy.first), outputName));
322 return StatusCode::SUCCESS;
323 }
324 };
325
326 template<>
328 {
330 public:
331 typedef std::decay<decltype(
332 *(std::declval<EL::AnaAlgorithm>().evtStore()))>::type StoreType;
333 static StatusCode
334 getCopy (MsgStream& msgStream, StoreType& store,
336 const xAOD::IParticleContainer *inputObject,
337 const std::string& outputName, const std::string& auxName);
338 };
339 }
340}
341
342#endif
macros for messaging and checking status codes
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
Define macros for attributes used to control the static checker.
void record(const T *p, const std::string &key)
Definition TestStore.h:81
Manage index tracking and synchronization of auxiliary data.
Class providing the definition of the 4-vector interface.
struct color C
Select isolated Photons, Electrons and Muons.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
STL namespace.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxContainer > > shallowCopyContainer(const T &cont, const EventContext &ctx)
Function making a shallow copy of a constant container.
bool setOriginalObjectLink(const IParticle &original, IParticle &copy)
This function should be used by CP tools when they make a deep copy of an object in their correctedCo...
std::pair< std::unique_ptr< T >, std::unique_ptr< ShallowAuxInfo > > shallowCopyObject(const T &obj, const EventContext &ctx)
Function making a shallow copy of a constant standalone object.
void ClearTransientTrees ATLAS_NOT_THREAD_SAFE()
Function cleaning up the managed memory.
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.
check what kind of object/container the argument is
static std::true_type test_container(checker< C, decltype((*(const SG::AuxVectorBase **) nullptr)=((C *) nullptr))> *)
static std::false_type test_iparticle(...)
static std::false_type test_container(...)
static std::true_type test_iparticle(checker< C, decltype((*(const xAOD::IParticle **) nullptr)=((C *) nullptr) ->at(0))> *)
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, T *&object, const T *inputObject, const std::string &outputName, const std::string &auxName)
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, T *&object, const T *inputObject, const std::string &outputName, const std::string &auxName)
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, T *&object, const T *inputObject, const std::string &outputName, const std::string &auxName)
std::decay< decltype(*(std::declval< EL::AnaAlgorithm >().evtStore()))>::type StoreType
the type of the event store we use
static StatusCode getCopy(MsgStream &msgStream, StoreType &store, xAOD::IParticleContainer *&object, const xAOD::IParticleContainer *inputObject, const std::string &outputName, const std::string &auxName)
a helper class to create shallow copies and register them in the event store
MsgStream & msg
Definition testRead.cxx:32