ATLAS Offline Software
Loading...
Searching...
No Matches
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

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...
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

namespace  SG
 Forward declaration.

Macros

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

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);
#define SG_BASES(D,...)
Declare the base classes from which D derives.

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));
#define SG_VIRTUAL(T)
Used to mark virtual derivation.

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> >;
};
}
Forward declaration.
unsigned long long T
Traits class to hold derivation information.
Definition Bases.h:115
BaseList<> bases
Definition Bases.h:117

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)
uint32_t CLID
The Class ID type.

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));
}
}
}
};
static Double_t sz
Derived DataVector<T>.
Definition DataVector.h:795
void reserve(size_type n)
Attempt to preallocate enough memory for a specified number of elements.
value_type push_back(value_type pElem)
Add an element to the end of the collection.
size_type size() const noexcept
Returns the number of elements in the collection.
void clear()
Erase all the elements in the collection.
Base class for copy conversions, templated on source and destination classes.
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...
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts

You then declare this using the macro

MyCopyConversion);
#define SG_ADD_COPY_CONVERSION(D, C)
Declare a copy conversion from class T using converter C.

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,
B )
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 {};
SG_ADD_BASE (D, B);
#define SG_ADD_BASE(D, B)
Add a new base class B to class D.

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

325#define SG_ADD_BASE(D, B) \
326 namespace SG { \
327 template struct AddBaseInit<D, B >; \
328} struct sg_dummy // to swallow semicolon

◆ 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 336 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

336#define SG_ADD_COPY_CONVERSION(D, C) \
337 namespace SG { \
338 template struct AddCopyConversionInit<D, C >; \
339} struct sg_dummy // to swallow semicolon

◆ SG_BASE

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

Declare that class D derives from class B.

Example:

struct B {};
struct D : public B {};
SG_BASE (D, B);
#define SG_BASE(D, B)
Declare that class D derives from class B.

Definition at line 243 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 224 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.

224#define SG_BASES(D, ...) \
225 namespace SG { \
226 template<> struct Bases<D >{ \
227 using bases = BaseList<__VA_ARGS__>; \
228 }; \
229 template struct RegisterBaseInit<D >; \
230 template struct BaseInit<D >; \
231} struct sg_dummy // to swallow semicolon

◆ SG_BASES1

#define SG_BASES1 ( D,
B )
Value:
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);
#define SG_BASES1(D, B)
Declare that class D derives from class B.

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

◆ SG_BASES2

#define SG_BASES2 ( D,
B1,
B2 )
Value:
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);
#define SG_BASES2(D, B1, B2)
Declare that class D derives from classes B1 and B2.

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

◆ SG_BASES3

#define SG_BASES3 ( D,
B1,
B2,
B3 )
Value:
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);
#define SG_BASES3(D, B1, B2, B3)
Declare that class D derives from classes B1, B2, and B3.

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

◆ SG_BASES4

#define SG_BASES4 ( D,
B1,
B2,
B3,
B4 )
Value:
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);
#define SG_BASES4(D, B1, B2, B3, B4)
Declare that class D derives from classes B1, B2, B3, and B4.

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

◆ SG_VIRTUAL

#define SG_VIRTUAL ( T)
Value:
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 211 of file Control/AthenaKernel/AthenaKernel/BaseInfo.h.