ATLAS Offline Software
Classes | Namespaces | Macros
Control/AthenaKernel/AthenaKernel/BaseInfo.h File Reference

Provide an interface for finding inheritance information at run time. More...

#include "CxxUtils/checker_macros.h"
#include "AthenaKernel/Bases.h"
#include "GaudiKernel/ClassID.h"
#include <vector>
#include <typeinfo>
#include <type_traits>
#include "AthenaKernel/BaseInfo.icc"
Include dependency graph for Control/AthenaKernel/AthenaKernel/BaseInfo.h:

Go to the source code of this file.

Classes

struct  SG::BaseType< T >
 Helper metafunction to get base class types. More...
 
class  SG::BaseInfoImpl< T >
 
class  SG::CopyConversionBase
 Base class for copy conversions. More...
 
class  SG::CopyConversion< SRC, DST >
 Base class for copy conversions, templated on source and destination classes. More...
 
struct  SG::RegisterAddBaseInit< D, B >
 
struct  SG::RegisterAddCopyConversionInit< D, B >
 
class  SG::BaseInfoBase
 The non-template portion of the BaseInfo implementation. More...
 
class  SG::BaseInfo< T >
 Provide an interface for finding inheritance information at run time. More...
 

Namespaces

 SG
 Forward declaration.
 

Macros

#define SG_VIRTUAL(T)   Virtual<T>
 Used to mark virtual derivation. More...
 
#define SG_BASES(D, ...)
 Declare the base classes from which D derives. More...
 
#define SG_BASE(D, B)   SG_BASES(D, B)
 Declare that class D derives from class B. More...
 
#define SG_BASES1(D, B)   SG_BASES(D, B)
 Declare that class D derives from class B. More...
 
#define SG_BASES2(D, B1, B2)   SG_BASES(D, B1, B2)
 Declare that class D derives from classes B1 and B2. More...
 
#define SG_BASES3(D, B1, B2, B3)   SG_BASES(D, B1, B2, B3)
 Declare that class D derives from classes B1, B2, and B3. More...
 
#define SG_BASES4(D, B1, B2, B3, B4)   SG_BASES(D, B1, B2, B3, B4)
 Declare that class D derives from classes B1, B2, B3, and B4. More...
 
#define SG_ADD_BASE(D, B)
 Add a new base class B to class D. More...
 
#define SG_ADD_COPY_CONVERSION(D, C)
 Declare a copy conversion from class T using converter C. More...
 

Detailed Description

Provide an interface for finding inheritance information at run time.

Author
scott snyder
Date
Nov 2005 The SG::BaseInfo<T> class provides an interface for finding inheritance information about class T. In the absence of compiler support for reflection, the inheritance information must be explicitly declared. This is done with the SG_BASES macro and friends. To declare that class D derives from class B, use
struct B {};
struct D : public B {};
SG_BASES (D, B);

SG_BASES can take any number of base classes as arguments:

struct B1 {};
struct B2 {};
struct B3 {};
struct D : public B1, public B2, public B3 {};
SG_BASES (D, B1, B2, B3);

For backwards compatibility, there are also macros which take a fixed number of base class arguments: SG_BASE, SG_BASES1, SG_BASES2, SG_BASES3, and SG_BASES4.

If any of the derivations are virtual, the corresponding base class should be within a SG_VIRTUAL macro:

struct B1 {};
struct B2 {};
struct D : public B1, virtual public B2 {};
SG_BASES (D, B1, SG_VIRTUAL (B2));

Note that these macros will only work with non-templated types, or with specific instantiations of templated types. If you want a templated SG_BASES, you'll need to declare the specialization yourself. You should specialize SG::Bases<T>, defining the type bases to be a BaseList of the bases. Example:

template <class T> struct B {};
template <class T> struct D : public B<T> {};
namespace SG {
template <class T>
struct Bases<D<T> > {
using bases = BaseList<B<T> >;
};
}

Once these declarations are in place, what can you do with it? The interface is provided by the SG::BaseInfo<T> class. (This is a wrapper around a singleton, so it's not expensive to create instances of this class.) You can specify the base classes either by the Gaudi class ID or by the C++ std::type_info. Of course, you'll only be able to get information by class ID if the classes actually have IDs defined.

Here are the available methods of SG::BaseInfo<T>:

static bool is_base (CLID clid)
static bool is_base (const std::type_info& tinfo)

Test to see if the type given by clid or tinfo is a base of T. Note that T counts as its own base.

static bool is_virtual (CLID clid)
static bool is_virtual (const std::type_info& tinfo)

Test to see if the type given by clid or tinfo is a virtual base of T. This should always be false for T itself.

static void* cast (T* p, CLID clid)
static void* cast (T* p, const std::type_info& tinfo)

Cast a pointer from T* to a pointer to the type given by clid or tinfo, which must be a base if T known to BaseInfo. The result is returned as a void*. If the conversion cannot be done (because the target is not known to be a base of T), then 0 is returned.

static T* castTo (void* p, CLID clid)
static T* castTo (void* p, const std::type_info& tinfo)

Similar, except converts from a pointer to the type given by clid or tinfo (which must be a base of T) to T*. This involves a dynamic_cast. Returns 0 if the cast fails.

static const std::vector<CLID>& get_bases ()

Return all the known bases of T (that have class IDs). T itself will be included in this list.

static std::vector<const std::type_info*> get_ti_bases ()

Return all the known bases of T. T itself will be included in this list.

It is also possible to get a non-templated version of SG::BaseInfo<T>. This is called SG::BaseInfoBase. These objects can be found using SG::BaseInfoBase::find, by either class ID or std::type_info (in order for this to work, the corresponding SG::BaseInfo<T> class must have been used somewhere in the program). The interface of SG::BaseInfoBase is the same as SG::BaseInfo<T>, except that void* replaces T* in the cast methods.

Initialization issues: We don't want to build the SG::BaseInfo<T> objects at static initialization time. But we do need to remember which ones are available. Thus, BaseInfoBase maintains a list of CLIDs and std::type_info's for which we may not have done initialization, along with a function to call to do the initialization. The initialization list is filled during static initialization. When we look for an instance, if we don't find one, we look in the initialization list; if there's a match there, we run the initialization and remove it from the list.

Copy conversions: The conversion machinery above provides access to the standard C++ base<>derived conversions. However, sometimes you'd like to allow additional conversions as well, for example between a vector<ElementLink<T> > and DataVector<T>. For those cases, you can register a conversion function with the source type that can initialize an instance of the destination type from the source type. Then, when you try to retrieve the object from StoreGate with the destination type, your conversion function will be called.

Your conversion function should be the method convert of a class deriving from the SG::CopyConversion template; for example,

class MyCopyConversion
: public SG::CopyConversion<std::vector<ElementLink<MyType> >,
DataVector<MyType> >
{
public:
virtual void convert (const std::vector<ElementLink<MyType> >& src,
DataVector<MyType>& dst) const
{
size_t sz = src.size();
if (dst.size() != sz) {
dst.reserve (sz);
for (size_t i = 0; i < sz; i++) {
const MyType* p = *(src[i]).cptr();
dst.push_back (const_cast<MyType*> (p));
}
}
}
};

You then declare this using the macro

MyCopyConversion);

Copy conversions are enabled only for objects that have been marked as const.

Definition in file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

Macro Definition Documentation

◆ SG_ADD_BASE

#define SG_ADD_BASE (   D,
 
)
Value:
namespace SG { \
template struct AddBaseInit<D, B >; \
} struct sg_dummy

Add a new base class B to class D.

Sometimes, the SG_BASES macro for a class isn't present in its header.

One can try to put the appropriate SG_BASES macro somewhere else, but this doesn't always work: if the BaseInfoBase for D has already been created by the time the SG_BASES initialization runs, then that SG_BASES macro won't do anything.

SG_ADD_BASE, however, will add a new base to an existing BaseInfoBase.

Beware, though. that any bases added this way will not be visited by Bases<T>::bases::foreach_.

struct B {};
struct D : public B {};

Definition at line 326 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_ADD_COPY_CONVERSION

#define SG_ADD_COPY_CONVERSION (   D,
  C 
)
Value:
namespace SG { \
template struct AddCopyConversionInit<D, C >; \
} struct sg_dummy

Declare a copy conversion from class T using converter C.

See the comments in the header for a detailed description.

Definition at line 337 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_BASE

#define SG_BASE (   D,
 
)    SG_BASES(D, B)

Declare that class D derives from class B.

Example:

struct B {};
struct D : public B {};
SG_BASE (D, B);

Definition at line 244 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_BASES

#define SG_BASES (   D,
  ... 
)
Value:
namespace SG { \
template<> struct Bases<D >{ \
using bases = BaseList<__VA_ARGS__>; \
}; \
template struct RegisterBaseInit<D >; \
template struct BaseInit<D >; \
} struct sg_dummy

Declare the base classes from which D derives.

Example:

struct B1 {};
struct B2 {};
struct D : public B1, public B2 {};
SG_BASES (D, B1, B2);

Definition at line 225 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_BASES1

#define SG_BASES1 (   D,
 
)    SG_BASES(D, B)

Declare that class D derives from class B.

This is the same as SG_BASE. Example:

struct B {};
struct D : public B {};
SG_BASES1 (D, B);

Definition at line 257 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_BASES2

#define SG_BASES2 (   D,
  B1,
  B2 
)    SG_BASES(D, B1, B2)

Declare that class D derives from classes B1 and B2.

Example:

struct B1 {};
struct B2 {};
struct D : public B1, public B2 {};
SG_BASES2 (D, B1, B2);

Definition at line 271 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_BASES3

#define SG_BASES3 (   D,
  B1,
  B2,
  B3 
)    SG_BASES(D, B1, B2, B3)

Declare that class D derives from classes B1, B2, and B3.

Example:

struct B1 {};
struct B2 {};
struct B3 {};
struct D : public B1, public B2, public B3 {};
SG_BASES3 (D, B1, B2, B3);

Definition at line 286 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_BASES4

#define SG_BASES4 (   D,
  B1,
  B2,
  B3,
  B4 
)    SG_BASES(D, B1, B2, B3, B4)

Declare that class D derives from classes B1, B2, B3, and B4.

Example:

struct B1 {};
struct B2 {};
struct B3 {};
struct B4 {};
struct D : public B1, public B2, public B3, public B4 {};
SG_BASES4 (D, B1, B2, B3, B4);

Definition at line 302 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

◆ SG_VIRTUAL

#define SG_VIRTUAL (   T)    Virtual<T>

Used to mark virtual derivation.

When using the SG_BASES macros below, use this in the case of virtual derivation. Example:

struct B1 {};
struct B2 {};
struct D : public B1, virtual public B2 {};
SG_BASES (D, B1, SG_VIRTUAL (B2));

Definition at line 212 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

DataVector::reserve
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
SG_ADD_BASE
#define SG_ADD_BASE(D, B)
Add a new base class B to class D.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:325
SG_BASES
#define SG_BASES(D,...)
Declare the base classes from which D derives.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:224
fitman.sz
sz
Definition: fitman.py:527
SG
Forward declaration.
Definition: CaloCellPacker_400_500.h:32
SG::VIEW_ELEMENTS
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
Definition: OwnershipPolicy.h:18
WriteCellNoiseToCool.src
src
Definition: WriteCellNoiseToCool.py:513
SG::CopyConversion
Base class for copy conversions, templated on source and destination classes.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:408
DMTest::C
C_v1 C
Definition: C.h:26
SG_ADD_COPY_CONVERSION
#define SG_ADD_COPY_CONVERSION(D, C)
Declare a copy conversion from class T using converter C.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:336
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
SG_BASE
#define SG_BASE(D, B)
Declare that class D derives from class B.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:243
lumiFormat.i
int i
Definition: lumiFormat.py:85
SG_BASES2
SG_BASES2(Rec::TrackParticle, SG_VIRTUAL(INavigable4Momentum), Trk::TrackParticleBase)
SG::CopyConversion::convert
virtual void convert(const SRC &src, DST &dst) const =0
Convert the contents of an instance of the source class SRC to an instance of the destination class D...
SG::Bases::bases
BaseList<> bases
Definition: Bases.h:112
DataVector
Derived DataVector<T>.
Definition: DataVector.h:581
CLID
uint32_t CLID
The Class ID type.
Definition: Event/xAOD/xAODCore/xAODCore/ClassID_traits.h:47
DataVector::clear
void clear()
Erase all the elements in the collection.
SG_BASES3
#define SG_BASES3(D, B1, B2, B3)
Declare that class D derives from classes B1, B2, and B3.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:285
DataVector::push_back
value_type push_back(value_type pElem)
Add an element to the end of the collection.
dqt_zlumi_alleff_HIST.B
B
Definition: dqt_zlumi_alleff_HIST.py:110
SG_VIRTUAL
#define SG_VIRTUAL(T)
Used to mark virtual derivation.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:211
SG_BASES4
#define SG_BASES4(D, B1, B2, B3, B4)
Declare that class D derives from classes B1, B2, B3, and B4.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:301
DataVector::size
size_type size() const noexcept
Returns the number of elements in the collection.
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
SG_BASES1
#define SG_BASES1(D, B)
Declare that class D derives from class B.
Definition: Control/AthenaKernel/AthenaKernel/BaseInfo.h:256