diff --git a/Control/AthenaKernel/AthenaKernel/BaseInfo.h b/Control/AthenaKernel/AthenaKernel/BaseInfo.h index dd2b38654b38eb1066395f76bd9bb0880fef1f8d..9f05c8a32ac7e538d10c0271571429b99e786c50 100755 --- a/Control/AthenaKernel/AthenaKernel/BaseInfo.h +++ b/Control/AthenaKernel/AthenaKernel/BaseInfo.h @@ -12,28 +12,28 @@ * The @a SG::BaseInfo<T> class provides an interface for finding * inheritance information about class @a T. In the absence of compiler * support for reflection, the inheritance information must be - * explicitly declared. This is done with the @a SG_BASE macro + * explicitly declared. This is done with the @a SG_BASES macro * and friends. To declare that class @a D derives from class @a B, use * *@code * struct B {}; * struct D : public B {}; - * SG_BASE (D, B); + * SG_BASES (D, B); @endcode * - * You can also use multiple inheritance with the @a SG_BASES2 - * and @a SG_BASES3 macros: + * @a SG_BASES can take any number of base classes as arguments: * *@code * struct B1 {}; * struct B2 {}; * struct B3 {}; * struct D : public B1, public B2, public B3 {}; - * SG_BASES3 (D, B1, B2, B3); + * SG_BASES (D, B1, B2, B3); @endcode * - * Supporting more than three base classes requires (straightforward) - * changes to the code here. + * For backwards compatibility, there are also macros which + * take a fixed number of base class arguments: @a SG_BASE, @a SG_BASES1, + * @a SG_BASES2, @a SG_BASES3, and @a SG_BASES4. * * If any of the derivations are virtual, the corresponding * base class should be within a @a SG_VIRTUAL macro: @@ -42,15 +42,14 @@ * struct B1 {}; * struct B2 {}; * struct D : public B1, virtual public B2 {}; - * SG_BASES2 (D, B1, SG_VIRTUAL (B2)); + * SG_BASES (D, B1, SG_VIRTUAL (B2)); @endcode * * Note that these macros will only work with non-templated types, * or with specific instantiations of templated types. If you want - * a templated @a SG_BASE, you'll need to declare the specialization - * yourself. You should specialize @a SG::Bases<T>, defining types - * @a Base1, @a Base2, and @a Base3 (which should be @a SG::NoBase - * if not used). Example: + * a templated @a SG_BASES, you'll need to declare the specialization + * yourself. You should specialize @a SG::Bases<T>, defining the + * type @a bases to be a @c BaseList of the bases. Example: * *@code * template <class T> struct B {}; @@ -58,9 +57,7 @@ * namespace SG { * template <class T> * struct Bases<D<T> > { - * typedef B<T> Base1; - * typedef NoBase Base2; - * typedef NoBase Base3; + * using bases = BaseList<B<T> >; * }; * } @endcode @@ -201,19 +198,39 @@ /** * @brief Used to mark virtual derivation. - * When using the @a SG_BASE macros below, use this in the case + * When using the @a SG_BASES macros below, use this in the case * of virtual derivation. Example: * *@code * struct B1 {}; * struct B2 {}; * struct D : public B1, virtual public B2 {}; - * SG_BASES2 (D, B1, SG_VIRTUAL (B2)); + * SG_BASES (D, B1, SG_VIRTUAL (B2)); @endcode */ #define SG_VIRTUAL(T) Virtual<T> +/** + * @brief Declare the base classes from which @a D derives. Example: + * + *@code + * struct B1 {}; + * struct B2 {}; + * struct D : public B1, public B2 {}; + * SG_BASES (D, B1, B2); + @endcode + */ +#define SG_BASES(D, ...) \ + namespace SG { \ + template<> struct Bases<D >{ \ + using bases = BaseList<__VA_ARGS__>; \ + }; \ + template struct RegisterBaseInit<D >; \ + template struct BaseInit<D >; \ +} struct sg_dummy // to swallow semicolon + + /** * @brief Declare that class @a D derives from class @a B. Example: * @@ -223,7 +240,7 @@ * SG_BASE (D, B); @endcode */ -#define SG_BASE(D, B) SG_BASES1(D, B) +#define SG_BASE(D, B) SG_BASES(D, B) /** @@ -236,18 +253,7 @@ * SG_BASES1 (D, B); @endcode */ -#define SG_BASES1(D, B) \ - namespace SG { \ - template<> struct Bases<D >{ \ - typedef B Base1; \ - typedef NoBase Base2; \ - typedef NoBase Base3; \ - typedef NoBase Base4; \ - using bases = BaseList<B>; \ - }; \ - template struct RegisterBaseInit<D >; \ - template struct BaseInit<D >; \ -} struct sg_dummy // to swallow semicolon +#define SG_BASES1(D, B) SG_BASES(D, B) /** @@ -261,18 +267,7 @@ * SG_BASES2 (D, B1, B2); @endcode */ -#define SG_BASES2(D, B1, B2) \ - namespace SG { \ - template<> struct Bases<D >{ \ - typedef B1 Base1; \ - typedef B2 Base2; \ - typedef NoBase Base3; \ - typedef NoBase Base4; \ - using bases = BaseList<B1,B2>; \ - }; \ - template struct RegisterBaseInit<D >; \ - template struct BaseInit<D >; \ -} struct sg_dummy // to swallow semicolon +#define SG_BASES2(D, B1, B2) SG_BASES(D, B1, B2) /** @@ -287,18 +282,7 @@ * SG_BASES3 (D, B1, B2, B3); @endcode */ -#define SG_BASES3(D, B1, B2, B3) \ - namespace SG { \ - template<> struct Bases<D >{ \ - typedef B1 Base1; \ - typedef B2 Base2; \ - typedef B3 Base3; \ - typedef NoBase Base4; \ - using bases = BaseList<B1,B2,B3>; \ - }; \ - template struct RegisterBaseInit<D >; \ - template struct BaseInit<D >; \ -} struct sg_dummy // to swallow semicolon +#define SG_BASES3(D, B1, B2, B3) SG_BASES(D, B1, B2, B3) /** @@ -314,32 +298,24 @@ * SG_BASES4 (D, B1, B2, B3, B4); @endcode */ -#define SG_BASES4(D, B1, B2, B3, B4) \ - namespace SG { \ - template<> struct Bases<D >{ \ - typedef B1 Base1; \ - typedef B2 Base2; \ - typedef B3 Base3; \ - typedef B4 Base4; \ - using bases = BaseList<B1,B2,B3,B4>; \ - }; \ - template struct RegisterBaseInit<D >; \ - template struct BaseInit<D >; \ -} struct sg_dummy // to swallow semicolon +#define SG_BASES4(D, B1, B2, B3, B4) SG_BASES(D, B1, B2, B3, B4) /** * @brief Add a new base class @c B to class @c D. * - * Sometimes, the SG_BASE macro for a class isn't present in its header. + * Sometimes, the SG_BASES macro for a class isn't present in its header. * - * One can try to put the appropriate SG_BASE macro somewhere else, + * One can try to put the appropriate SG_BASES macro somewhere else, * but this doesn't always work: if the @c BaseInfoBase for @c D has - * already been created by the time the @c SG_BASE initialization - * runs, then that @c SG_BASE macro won't do anything. + * already been created by the time the @c SG_BASES initialization + * runs, then that @c SG_BASES macro won't do anything. * * @c SG_ADD_BASE, however, will add a new base to an existing @c BaseInfoBase. * + * Beware, though. that any bases added this way will not be visited + * by Bases<T>::bases::foreach_. + * *@code * struct B {}; * struct D : public B {}; diff --git a/Control/AthenaKernel/AthenaKernel/BaseInfo.icc b/Control/AthenaKernel/AthenaKernel/BaseInfo.icc index 5fd344de40682445b79dace5679a5200103027c6..0fde1960a91f9b18458c959708392cdf1ace7ded 100755 --- a/Control/AthenaKernel/AthenaKernel/BaseInfo.icc +++ b/Control/AthenaKernel/AthenaKernel/BaseInfo.icc @@ -128,7 +128,7 @@ private: /** - * @brief Generic initializer for base @a B. + * @brief Initializer for base @a B. */ template <class B> struct BaseInfo_init @@ -141,43 +141,13 @@ struct BaseInfo_init c.template add_base<B>(is_virtual); // Then we recurse on each possible base. - BaseInfo_init<typename Bases<B>::Base1>::init (c, is_virtual); - BaseInfo_init<typename Bases<B>::Base2>::init (c, is_virtual); - BaseInfo_init<typename Bases<B>::Base3>::init (c, is_virtual); - BaseInfo_init<typename Bases<B>::Base4>::init (c, is_virtual); - } -}; - - -/** - * @brief Dummy initializer. - */ -template <> -struct BaseInfo_init<NoBase> -{ - template <class T> - static void init (BaseInfoImpl<T>& /*c*/, bool /*is_virtual*/) - { - // This gets called when there is no base in a slot - // (signaled by the use of @a NoBase). - // This ends the recursion. - } -}; - - -/** - * @brief Initializer for virtual base @a B. - */ -template <class B> -struct BaseInfo_init<Virtual<B> > -{ - template <class T> - static void init (BaseInfoImpl<T>& c, bool /*is_virtual*/) - { - // Here, we initialize the @a BaseInfo for @a T for a virtual - // base class @a B. We recurse to the generic initializer - // for this base, with the @a is_virtual flag forced on. - BaseInfo_init<B>::init (c, true); + auto add = [&] (auto* p, bool base_is_virtual) + { + using base_t = std::remove_pointer_t<decltype(p)>; + c.template add_base<base_t> (is_virtual || base_is_virtual); + return false; + }; + Bases<B>::bases::foreach_ (add); } }; diff --git a/Control/AthenaKernel/AthenaKernel/Bases.h b/Control/AthenaKernel/AthenaKernel/Bases.h index 47d7c7c34abaa94bf33a4a47b555d8c39e3e65eb..5b77f35bc36fd30b61235224c45f24a469d8e3e2 100644 --- a/Control/AthenaKernel/AthenaKernel/Bases.h +++ b/Control/AthenaKernel/AthenaKernel/Bases.h @@ -15,7 +15,7 @@ * [<CENSORED> Qt defines `foreach' as a macro, so we can't use that name!] * * For this to work, the @c Bases class must be specialized for each - * class @c T. This is usually done using the @c SG_BASE macros + * class @c T. This is usually done using the @c SG_BASES macro * defined in BaseInfo.h. */ @@ -57,6 +57,12 @@ struct BaseType<Virtual<T> > }; +/** + * @brief Marker to indicate a nonexistent base class. + */ +struct NoBase {}; + + /** * @brief Represent a list of base classes. * @@ -67,6 +73,10 @@ template <class... T> struct BaseList { public: + // First base in the list. + using Base1 = NoBase; + + /** * @brief Iterate over base classes. * @param f Object to call for each base class. @@ -86,12 +96,6 @@ public: }; -/** - * @brief Marker to indicate a nonexistent base class. - */ -struct NoBase {}; // Temporary for back-compatibility. - - /** * @brief Traits class to hold derivation information. * @@ -106,11 +110,6 @@ struct Bases { public: using bases = BaseList<>; - - typedef NoBase Base1; // Temporary for back-compatibility. - typedef NoBase Base2; - typedef NoBase Base3; - typedef NoBase Base4; }; @@ -121,6 +120,10 @@ template <class BASE, class... REST> struct BaseList<BASE, REST...> { public: + // First base in the list. + using Base1 = BASE; + + /** * @brief Iterate over base classes. * @param f Object to call for each base class. diff --git a/Control/AthenaKernel/AthenaKernel/CondCont.h b/Control/AthenaKernel/AthenaKernel/CondCont.h index 3281debb7ca3856c0e4e7a43572adf74169ae541..9bd4aabd215baa2cc003f89f7a24e4264823aa7b 100644 --- a/Control/AthenaKernel/AthenaKernel/CondCont.h +++ b/Control/AthenaKernel/AthenaKernel/CondCont.h @@ -797,10 +797,6 @@ template <typename T> struct Bases<CondCont<T> > { using bases = BaseList<CondContBase>; - typedef CondContBase Base1; - typedef NoBase Base2; - typedef NoBase Base3; - typedef NoBase Base4; }; } // namespace SG @@ -820,8 +816,8 @@ class CondContBaseInfo<D> \ public: \ typedef CondCont<B> Base; \ }; \ -SG_BASE(CondCont<D>, CondCont<B>); \ -SG_BASE(D, B) +SG_BASES(CondCont<D>, CondCont<B>);\ +SG_BASES(D, B) diff --git a/Control/AthenaKernel/AthenaKernel/MetaCont.h b/Control/AthenaKernel/AthenaKernel/MetaCont.h index e7618ae8b606bc54663ff8c18511bcaa1fe1df11..cb3012a1a35455acf4b932a201d90b451200f1bf 100644 --- a/Control/AthenaKernel/AthenaKernel/MetaCont.h +++ b/Control/AthenaKernel/AthenaKernel/MetaCont.h @@ -220,7 +220,7 @@ CLASS_DEF( MetaContBase , 34480469 , 1 ) // #define METACONT_DEF(T, CLID) \ CLASS_DEF( MetaCont<T>, CLID, 1 ) \ - SG_BASE( MetaCont<T>, MetaContBase ) + SG_BASES( MetaCont<T>, MetaContBase ) #endif diff --git a/Control/AthenaKernel/AthenaKernel/StorableConversions.h b/Control/AthenaKernel/AthenaKernel/StorableConversions.h index 2c53f9d972052324138334e0e1439c090755f325..a0f3990a7d3824416009ed2ea2666b3763e95fdf 100755 --- a/Control/AthenaKernel/AthenaKernel/StorableConversions.h +++ b/Control/AthenaKernel/AthenaKernel/StorableConversions.h @@ -103,7 +103,7 @@ namespace SG { * to use instead @c SG::DVLDataBucket\<T>. * * Further, if @c T derives from @c DataVector or @c DataList (as declared - * by @c SG_BASE), then we also want to use @c SG::DVLDataBucket\<T>. + * by @c SG_BASES), then we also want to use @c SG::DVLDataBucket\<T>. * * Further, we don't want this code to depend on @c DataVector * or @c SG::DVLDataBucket. That behavior is enabled only @@ -132,7 +132,7 @@ namespace SG { struct DataBucketTrait { // The first base of @c T (or @c SG::NoBase). - typedef typename SG::BaseType<typename SG::Bases<T>::Base1>::type base1; + typedef typename SG::BaseType<typename SG::Bases<T>::bases::Base1>::type base1; // Test to see if it's valid. typedef typename boost::is_same<base1, SG::NoBase>::type has_base; diff --git a/Control/AthenaKernel/AthenaKernel/TopBase.h b/Control/AthenaKernel/AthenaKernel/TopBase.h index c6ae01e542da85eed1eb06c96dc4e313ee885ed3..6386b655a5384ad6cdfa27d6b9e40e352f69c54b 100644 --- a/Control/AthenaKernel/AthenaKernel/TopBase.h +++ b/Control/AthenaKernel/AthenaKernel/TopBase.h @@ -1,13 +1,12 @@ // This file's extension implies that it's C, but it's really -*- C++ -*-. /* - * Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration. + * Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration. */ -// $Id$ /** * @file AthenaKernel/TopBase.h * @author scott snyder <snyder@bnl.gov> * @date Jan, 2018 - * @brief Calculate topmost accessible base accessible via SG_BASE. + * @brief Calculate topmost accessible base accessible via SG_BASES. */ @@ -23,13 +22,13 @@ namespace SG { /** - * @brief Calculate topmost base accessible via SG_BASE. + * @brief Calculate topmost base accessible via SG_BASES. * * For example, if we have * *@code - * SG_BASE(C2, C1); - * SG_BASE(C3, C2); + * SG_BASES(C2, C1); + * SG_BASES(C3, C2); @endcode * * then TopBase<C1>::type, TopBase<C2>::type, and TopBase<C3>::type all yield @c C1. @@ -37,7 +36,7 @@ namespace SG { template <class T> struct TopBase { - typedef typename SG::Bases<T>::Base1 Base1; + typedef typename SG::Bases<T>::bases::Base1 Base1; static const bool has_base = !std::is_same<Base1, SG::NoBase>::value; typedef typename std::conditional<has_base, typename TopBase<Base1>::type, diff --git a/Control/AthenaKernel/test/BaseInfo_test.cxx b/Control/AthenaKernel/test/BaseInfo_test.cxx index 981e046e1aa92932cb4ffc9bbd5e6fa06c627b2e..57a86cbc7b74b11aeeb2d6a52e39f45455dbeead 100755 --- a/Control/AthenaKernel/test/BaseInfo_test.cxx +++ b/Control/AthenaKernel/test/BaseInfo_test.cxx @@ -1,8 +1,6 @@ /* - Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ - -// $Id$ /** * @file AthenaKernel/test/BaseInfo_test.cxx * @author scott snyder @@ -38,8 +36,8 @@ struct CC : public BB CC (int the_x=0) : BB(the_x) {} }; -SG_BASE(BB, AA); -SG_BASE(CC, BB); +SG_BASES(BB, AA); +SG_BASES(CC, BB); CLASS_DEF (AA, 1111, 2) CLASS_DEF (BB, 1112, 2) @@ -69,13 +67,13 @@ CLASS_DEF (N, 1115, 2) CLASS_DEF (O, 1116, 2) CLASS_DEF (P, 1117, 2) -SG_BASE (N, SG_VIRTUAL (M)); -SG_BASE (O, SG_VIRTUAL (M)); -SG_BASES2 (P, SG_VIRTUAL (N), SG_VIRTUAL (O)); +SG_BASES (N, SG_VIRTUAL (M)); +SG_BASES (O, SG_VIRTUAL (M)); +SG_BASES (P, SG_VIRTUAL (N), SG_VIRTUAL (O)); struct X1 {}; struct X2 : public X1 {}; -SG_BASE (X2, X1); +SG_BASES (X2, X1); struct Q : virtual public M { @@ -89,20 +87,20 @@ struct R : virtual public N, virtual public O, virtual public Q CLASS_DEF (Q, 1118, 2) CLASS_DEF (R, 1119, 2) -SG_BASE (Q, SG_VIRTUAL (M)); -SG_BASES3 (R, SG_VIRTUAL (N), - SG_VIRTUAL (O), - SG_VIRTUAL (Q)); +SG_BASES (Q, SG_VIRTUAL (M)); +SG_BASES (R, SG_VIRTUAL (N), + SG_VIRTUAL (O), + SG_VIRTUAL (Q)); struct I1 : public AA {}; struct I2 : public AA {}; -SG_BASE (I1, AA); -SG_BASE (I2, AA); +SG_BASES (I1, AA); +SG_BASES (I2, AA); CLASS_DEF (I2, 1120, 2) struct J : public AA, virtual public X1, public M {}; -SG_BASE(J, AA); +SG_BASES(J, AA); SG_ADD_BASE(J, SG_VIRTUAL(X1)); SG_ADD_BASE(J, M); @@ -246,12 +244,12 @@ int test1() assert (SG::BaseInfoBase::find (99999) == 0); assert (SG::BaseInfoBase::find (typeid(int)) == 0); - assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::type) == typeid(AA)); - assert (typeid(SG::BaseType<SG::Bases<BB>::Base1>::is_virtual) == + assert (typeid(SG::BaseType<SG::Bases<BB>::bases::Base1>::type) == typeid(AA)); + assert (typeid(SG::BaseType<SG::Bases<BB>::bases::Base1>::is_virtual) == typeid(std::false_type)); - assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::type) == typeid(M)); - assert (typeid(SG::BaseType<SG::Bases<N>::Base1>::is_virtual) == + assert (typeid(SG::BaseType<SG::Bases<N>::bases::Base1>::type) == typeid(M)); + assert (typeid(SG::BaseType<SG::Bases<N>::bases::Base1>::is_virtual) == typeid(std::true_type)); std::vector<CLID> exp3 = list_of diff --git a/Control/AthenaKernel/test/DataBucket_test.cxx b/Control/AthenaKernel/test/DataBucket_test.cxx index 4377bbaf399bfbff99f56b075122c2da349572bc..6df79da82ed138294d2b2f54c4b123cf1a6691cc 100755 --- a/Control/AthenaKernel/test/DataBucket_test.cxx +++ b/Control/AthenaKernel/test/DataBucket_test.cxx @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ #undef NDEBUG @@ -120,7 +120,7 @@ struct X2 CLASS_DEF(X1, 8011, 1) CLASS_DEF(X2, 8012, 1) -SG_BASE(X2, X1); +SG_BASES(X2, X1); CLASS_DEF( const int* , 206871866 , 1 ) diff --git a/Control/AthenaKernel/test/MetaContDataBucket_test.cxx b/Control/AthenaKernel/test/MetaContDataBucket_test.cxx index 727127e2559e72e8ba426f8596abd509d794f0e1..feaeec8d933c796577f46132353b34a72eb9d789 100644 --- a/Control/AthenaKernel/test/MetaContDataBucket_test.cxx +++ b/Control/AthenaKernel/test/MetaContDataBucket_test.cxx @@ -1,10 +1,6 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ -/* - */ - -// $Id$ /** * @file AthenaKernel/test/MetaContDataBucket_test.cxx * @author scott snyder <snyder@bnl.gov> @@ -91,7 +87,7 @@ CLASS_DEF( TestContBase, 98770271, 1 ) CLASS_DEF( TestCont, 86960140, 1 ) CLASS_DEF( TestPayload, 128629149, 1 ) -SG_BASE( TestCont, TestContBase ); +SG_BASES( TestCont, TestContBase ); void test1() diff --git a/Control/AthenaKernel/test/TopBase_test.cxx b/Control/AthenaKernel/test/TopBase_test.cxx index 2b4cb64003548133aeabf7323560ac6e3277aafc..f7ddda395795924803e41525f68e0b091924e9dd 100644 --- a/Control/AthenaKernel/test/TopBase_test.cxx +++ b/Control/AthenaKernel/test/TopBase_test.cxx @@ -1,9 +1,6 @@ /* - Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration */ -/* - */ - /** * @file AthenaKernel/test/TopBase_test.cxx * @author scott snyder <snyder@bnl.gov> @@ -23,8 +20,8 @@ class C2 : public C1 {}; class C3 : public C2 {}; -SG_BASE (C2, C1); -SG_BASE (C3, C2); +SG_BASES (C2, C1); +SG_BASES (C3, C2); void test1()