|
|
|||
File indexing completed on 2026-09-14 09:05:24
0001 // SPDX-License-Identifier: LGPL-3.0-or-later 0002 // Copyright (C) 2025 Wouter Deconinck 0003 // 0004 // Modern datamodel glue for podio >= 1.3 0005 // This file uses podio's built-in TypeList support instead of code generation 0006 // 0007 // **WARNING: This header includes ALL PODIO types (may add significant compile time)** 0008 // Only include this if you need VisitPodioCollection visitor pattern. 0009 // 0010 // For factories using PodioInput/PodioOutput, include JOmniFactory.h which provides 0011 // PodioTypeMap type traits without the overhead of all collection types. 0012 0013 #pragma once 0014 0015 #include <stdexcept> 0016 #include <string_view> 0017 #include <unordered_map> 0018 #include <type_traits> 0019 #include <format> 0020 #include <podio/CollectionBase.h> 0021 #include <podio/utilities/TypeHelpers.h> 0022 // Include umbrella headers for TypeList support 0023 // Only files that use the visitor pattern need this full header 0024 // IWYU pragma: begin_exports 0025 #include <edm4hep/edm4hep.h> 0026 #include <edm4eic/edm4eic.h> 0027 // IWYU pragma: end_exports 0028 0029 // CollectionVisitorMap builds a dispatch table from podio collection type names 0030 // to type-safe visitor functions for a given Visitor type. 0031 // 0032 // The Visitor template parameter is expected to be a callable type (e.g. a 0033 // functor, lambda, or class with operator()) that can be invoked for each 0034 // supported concrete collection type: 0035 // 0036 // void operator()(const ConcreteCollectionType&); 0037 // 0038 // CollectionVisitorMap is instantiated once per Visitor (see VisitPodioCollection 0039 // below). At construction time it registers all EDM4hep and EDM4eic data and 0040 // link collection types by mapping their static typeName to a function that 0041 // will: 0042 // 1. downcast the generic podio::CollectionBase reference to the concrete 0043 // collection type, and 0044 // 2. call the Visitor with that concrete collection. 0045 // 0046 // This map is then used by VisitPodioCollection to look up the correct 0047 // handler at runtime based on collection.getTypeName(), providing a 0048 // type-safe implementation of the visitor pattern over podio collections. 0049 template <typename Visitor> class CollectionVisitorMap { 0050 public: 0051 using FunctionType = void (*)(Visitor&, const podio::CollectionBase&); 0052 0053 private: 0054 std::unordered_map<std::string_view, FunctionType> m_map; 0055 0056 template <typename CollectionT> 0057 static void visitCollection(Visitor& visitor, const podio::CollectionBase& collection) { 0058 static_assert(std::is_base_of_v<podio::CollectionBase, CollectionT>, 0059 "CollectionT must be derived from podio::CollectionBase"); 0060 visitor(*static_cast<const CollectionT*>(&collection)); 0061 } 0062 0063 template <typename CollectionT> void addToMap() { 0064 m_map[CollectionT::typeName] = &visitCollection<CollectionT>; 0065 } 0066 0067 template <typename DataT> void addDataTypeToMap() { addToMap<typename DataT::collection_type>(); } 0068 0069 template <typename... DataTypes> 0070 void addAllDataCollections(podio::utils::TypeList<DataTypes...>) { 0071 (addDataTypeToMap<DataTypes>(), ...); 0072 } 0073 0074 template <typename... LinkTypes> 0075 void addAllLinkCollections(podio::utils::TypeList<LinkTypes...>) { 0076 (addDataTypeToMap<LinkTypes>(), ...); 0077 } 0078 0079 public: 0080 CollectionVisitorMap() { 0081 // Add all EDM4hep and EDM4eic data collection types 0082 addAllDataCollections(typename edm4hep::edm4hepDataTypes{}); 0083 addAllDataCollections(typename edm4eic::edm4eicDataTypes{}); 0084 0085 // Add all EDM4hep and EDM4eic link collections 0086 addAllLinkCollections(typename edm4hep::edm4hepLinkTypes{}); 0087 addAllLinkCollections(typename edm4eic::edm4eicLinkTypes{}); 0088 } 0089 0090 const auto& getMap() const { return m_map; } 0091 }; 0092 0093 // VisitPodioCollection is a visitor adaptor for type-safe processing of podio collections. 0094 // 0095 // This template implements a runtime-dispatch visitor pattern for 0096 // podio::CollectionBase instances. It uses the collection's 0097 // runtime type name together with CollectionVisitorMap to look up the 0098 // concrete collection type and call the provided @p Visitor on it. 0099 // 0100 // template parameter Visitor 0101 // A type that models a callable taking a const reference to each 0102 // supported concrete podio collection type. In practice, this means 0103 // that for every collection type CollectionT registered in 0104 // CollectionVisitorMap, the following expression must be well-formed: 0105 // 0106 // visitor(const CollectionT&); 0107 // 0108 // This can be satisfied either by giving Visitor a suitable 0109 // operator() overload, or by providing free / member functions 0110 // that are invocable with const CollectionT&. 0111 // 0112 // Usage: 0113 // - Construct or obtain a Visitor instance. 0114 // - Call VisitPodioCollection<Visitor>::operator() with the visitor 0115 // and a podio::CollectionBase reference. The adaptor will: 0116 // 1. Look up the collection's concrete type by getTypeName(). 0117 // 2. Cast the podio::CollectionBase to the matching concrete 0118 // collection type. 0119 // 3. Invoke the visitor with a const CollectionT& argument. 0120 // 0121 // If the collection type name is not known to the registered EDM4hep or 0122 // EDM4eic datamodels, operator() throws std::runtime_error with a 0123 // descriptive error message. 0124 template <typename Visitor> struct VisitPodioCollection { 0125 void operator()(Visitor& visitor, const podio::CollectionBase& collection) { 0126 // Build the map once (static initialization) 0127 static const CollectionVisitorMap<Visitor> visitorMap; 0128 0129 auto typeName = collection.getTypeName(); 0130 auto it = visitorMap.getMap().find(typeName); 0131 0132 if (it != visitorMap.getMap().end()) { 0133 it->second(visitor, collection); 0134 } else { 0135 throw std::runtime_error(std::format( 0136 "Unrecognized podio typename: {}.\n" 0137 "This type was not found in the supported datamodels (EDM4hep, EDM4eic).\n" 0138 "Possible causes:\n" 0139 " - The type is not defined in EDM4hep or EDM4eic datamodels.\n" 0140 " - You may be using an incompatible or outdated version of the datamodels.\n" 0141 " - There may be a typo in the type name.\n" 0142 "Please check your datamodel installation and ensure you are using compatible versions.", 0143 typeName)); 0144 } 0145 } 0146 };
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|