From 74c3cdea3b49a4b7ad2afe0ffaa4ea90b59032fb Mon Sep 17 00:00:00 2001
From: Frank Winklmeier <frank.winklmeier@cern.ch>
Date: Mon, 4 Nov 2024 14:57:39 +0100
Subject: [PATCH] AthToolSupport: support Gaudi interface base classes

Add support for the usage of the Gaudi `extends` formalism for interface
declarations. This removes the need to use the explicit `declareServiceInterface` calls.

Introduce the new `AsgTools/Interfaces.h` header that contains the
standalone versions of these classes. Also move the `DeclareInterfaceID`
here.
---
 .../AsgExampleTools/UnitTestService1.h        |  5 +--
 .../AsgExampleTools/Root/UnitTestService1.cxx |  6 +--
 .../AsgServices/AsgServices/AsgService.h      | 25 ------------
 .../AsgServices/AsgServices/IAsgService.h     | 13 +-----
 .../AsgServices/Root/AsgService.cxx           |  4 +-
 .../AsgTools/AsgTools/AsgComponent.h          |  3 +-
 .../AsgTools/AsgTools/Interfaces.h            | 40 +++++++++++++++++++
 7 files changed, 50 insertions(+), 46 deletions(-)
 create mode 100644 Control/AthToolSupport/AsgTools/AsgTools/Interfaces.h

diff --git a/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/UnitTestService1.h b/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/UnitTestService1.h
index f02c1b80b1d..54987f72a87 100644
--- a/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/UnitTestService1.h
+++ b/Control/AthToolSupport/AsgExampleTools/AsgExampleTools/UnitTestService1.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 /// @author Nils Krumnack
@@ -22,8 +22,7 @@ namespace asg
   /// This allows to unit test the various capabilities of
   /// AnaToolHandle in a controlled fashion.
 
-  struct UnitTestService1 : virtual public IUnitTestService1,
-                            public AsgService
+  struct UnitTestService1 : extends<AsgService, IUnitTestService1>
   {
     /// \brief standard constructor
   public:
diff --git a/Control/AthToolSupport/AsgExampleTools/Root/UnitTestService1.cxx b/Control/AthToolSupport/AsgExampleTools/Root/UnitTestService1.cxx
index d54453caca3..ee5b2d18a2a 100644
--- a/Control/AthToolSupport/AsgExampleTools/Root/UnitTestService1.cxx
+++ b/Control/AthToolSupport/AsgExampleTools/Root/UnitTestService1.cxx
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 /// @author Nils Krumnack
@@ -27,10 +27,8 @@ namespace asg
 {
   UnitTestService1 ::
   UnitTestService1 (const std::string& name, ISvcLocator* pSvcLocator)
-    : AsgService (name, pSvcLocator)
+    : base_class (name, pSvcLocator)
   {
-    declareServiceInterface<IUnitTestService1>();
-
     declareProperty ("propertyInt", m_propertyInt, "the integer property");
     declareProperty ("propertyString", m_propertyString, "the string property");
     declareProperty ("initializeFail", m_initializeFail, "whether initialize should fail");
diff --git a/Control/AthToolSupport/AsgServices/AsgServices/AsgService.h b/Control/AthToolSupport/AsgServices/AsgServices/AsgService.h
index 5c981396cd0..9612ba09572 100644
--- a/Control/AthToolSupport/AsgServices/AsgServices/AsgService.h
+++ b/Control/AthToolSupport/AsgServices/AsgServices/AsgService.h
@@ -39,17 +39,12 @@ namespace asg
   /// Loosely based on the \ref AsgTool implementation.
 
   class AsgService :
-#ifndef XAOD_STANDALONE
     public extends<AsgServiceBase, IAsgService>
-#else
-    public AsgServiceBase, public virtual IAsgService
-#endif
   {
   public:
     AsgService (const std::string& name,
                 ISvcLocator* pSvcLocator);
 
-
     /// set up/tear down functions
     /// \{
     virtual StatusCode initialize ();
@@ -59,28 +54,8 @@ namespace asg
     /// Print the state of the service
     virtual void print() const;
 
-    /// add the given interface to the list of interfaces
-    template<typename T> void declareServiceInterface ();
-
-
-#ifndef XAOD_STANDALONE
-  private:
-    /// list of interfaces we have
-    std::vector<std::pair<const InterfaceID& (*)(),void *(*)(AsgService*)>> m_interfaces;
-#endif
-
   }; // class AsgService
 
-
-
-  template<typename T>
-  void AsgService :: declareServiceInterface ()
-  {
-#ifndef XAOD_STANDALONE
-    m_interfaces.emplace_back (T::interfaceID, [] (AsgService *self) -> void* {return dynamic_cast<T*>(self);});
-#endif
-  }
-
 } // namespace asg
 
 #endif // ASGSERVICES_ASGSERVICE_H
diff --git a/Control/AthToolSupport/AsgServices/AsgServices/IAsgService.h b/Control/AthToolSupport/AsgServices/AsgServices/IAsgService.h
index ec2fbde00fb..d40ef203549 100644
--- a/Control/AthToolSupport/AsgServices/AsgServices/IAsgService.h
+++ b/Control/AthToolSupport/AsgServices/AsgServices/IAsgService.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 /// @author Nils Krumnack
@@ -13,16 +13,7 @@
 
 // Local include(s):
 #include "AsgMessaging/INamedInterface.h"
-
-#ifdef XAOD_STANDALONE
-/// \brief standalone version of the Gaudi interface declaration
-///
-/// This can't be a no-op, because the Gaudi version needs to be
-/// followed by a semicolon, so we need a statement that requires to
-/// be followed by a semi-colon.
-#define DeclareInterfaceID(iface, major, minor) \
-  static constexpr std::nullptr_t interfaceID = nullptr
-#endif
+#include "AsgTools/Interfaces.h"
 
 namespace asg
 {
diff --git a/Control/AthToolSupport/AsgServices/Root/AsgService.cxx b/Control/AthToolSupport/AsgServices/Root/AsgService.cxx
index e4b1aace018..178f1720c67 100644
--- a/Control/AthToolSupport/AsgServices/Root/AsgService.cxx
+++ b/Control/AthToolSupport/AsgServices/Root/AsgService.cxx
@@ -21,10 +21,10 @@ namespace asg
 #ifndef XAOD_STANDALONE
     : base_class(name, pSvcLocator)
 #else
-      : AsgServiceBase(name)
+    : base_class(name)
 #endif
    {
-     (void) pSvcLocator;
+     (void) pSvcLocator;  // suppress compiler warning in XAOD_STANDALONE
    }
 
   StatusCode AsgService ::
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/AsgComponent.h b/Control/AthToolSupport/AsgTools/AsgTools/AsgComponent.h
index dc7cdcdf4e5..58cbfbaf088 100644
--- a/Control/AthToolSupport/AsgTools/AsgTools/AsgComponent.h
+++ b/Control/AthToolSupport/AsgTools/AsgTools/AsgComponent.h
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
 */
 
 /// \author Nils Krumnack
@@ -15,6 +15,7 @@
 #include <AsgMessaging/INamedInterface.h>
 #include <AsgMessaging/MessageCheck.h>
 #include <AsgMessaging/MsgLevel.h>
+#include <AsgTools/Interfaces.h>
 #include <memory>
 #include <vector>
 
diff --git a/Control/AthToolSupport/AsgTools/AsgTools/Interfaces.h b/Control/AthToolSupport/AsgTools/AsgTools/Interfaces.h
new file mode 100644
index 00000000000..82a3f170c75
--- /dev/null
+++ b/Control/AthToolSupport/AsgTools/AsgTools/Interfaces.h
@@ -0,0 +1,40 @@
+/*
+  Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration
+*/
+#ifndef ASGTOOLS_INTERFACES_H
+#define ASGTOOLS_INTERFACES_H
+
+///
+/// Standalone versions of Gaudi interface declarations.
+//
+#if defined(XAOD_STANDALONE)
+
+/// This can't be a no-op, because the Gaudi version needs to be
+/// followed by a semicolon, so we need a statement that requires to
+/// be followed by a semi-colon.
+#define DeclareInterfaceID(iface, major, minor) \
+  static_assert(true)
+
+
+/// See GaudiKernel/extend_interfaces.h
+template <typename... Interfaces>
+struct extend_interfaces : virtual public Interfaces... {
+};
+
+
+/// See GaudiKernel/extends.h
+template <typename BASE, typename... Interfaces>
+struct extends : public BASE, virtual public extend_interfaces<Interfaces...> {
+  using base_class = extends;
+  using BASE::BASE;
+};
+
+
+/// See GaudiKernel/implements.h
+template <typename... Interfaces>
+struct implements : virtual public extend_interfaces<Interfaces...> {
+  using base_class = implements<Interfaces...>;
+};
+
+#endif
+#endif
-- 
GitLab