Skip to content

Commit

Permalink
Introduce type-alises for the two used map types
Browse files Browse the repository at this point in the history
  • Loading branch information
tmadlener committed Jun 30, 2023
1 parent 902ef98 commit 44b37f9
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 71 deletions.
146 changes: 79 additions & 67 deletions k4EDM4hep2LcioConv/include/k4EDM4hep2LcioConv/MappingUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

#include <optional>
#include <algorithm>
#include <vector>
#include <tuple>
#include <unordered_map>

#if __has_include("experimental/type_traits.h")
#include <experimental/type_traits>
Expand Down Expand Up @@ -42,84 +45,93 @@ namespace det {
} // namespace det
#endif

namespace k4EDM4hep2LcioConv::detail {
/// Very minimal detector for whether T is a map or not. We simply assume that
/// if it has a key_type we can also call find on T.
template<typename T>
using has_key_t = typename T::key_type;
namespace k4EDM4hep2LcioConv {

template<typename T>
constexpr static bool is_map_t = det::is_detected_v<has_key_t, T>;

/// Helper struct to determine the key and mapped types for map-like types or
/// maps
template<typename T, typename IsMap = std::bool_constant<is_map_t<T>>>
struct map_t_helper {};

template<typename T>
struct map_t_helper<T, std::bool_constant<true>> {
using key_type = typename T::key_type;
using mapped_type = typename T::mapped_type;
};
namespace detail {
/// Very minimal detector for whether T is a map or not. We simply assume that
/// if it has a key_type we can also call find on T.
template<typename T>
using has_key_t = typename T::key_type;

template<typename T>
constexpr static bool is_map_t = det::is_detected_v<has_key_t, T>;

/// Helper struct to determine the key and mapped types for map-like types or
/// maps
template<typename T, typename IsMap = std::bool_constant<is_map_t<T>>>
struct map_t_helper {};

template<typename T>
struct map_t_helper<T, std::bool_constant<true>> {
using key_type = typename T::key_type;
using mapped_type = typename T::mapped_type;
};

template<typename T>
struct map_t_helper<T, std::bool_constant<false>> {
using key_type = typename std::tuple_element<0, typename T::value_type>::type;
using mapped_type = typename std::tuple_element<1, typename T::value_type>::type;
};
template<typename T>
struct map_t_helper<T, std::bool_constant<false>> {
using key_type = typename std::tuple_element<0, typename T::value_type>::type;
using mapped_type = typename std::tuple_element<1, typename T::value_type>::type;
};

template<typename T>
using key_t = typename map_t_helper<T>::key_type;

template<typename T>
using mapped_t = typename map_t_helper<T>::mapped_type;

/**
* Find the mapped-to object in a map provided a key object
*
* NOTE: This will use a potentially more efficient lookup for actual map
* types (i.e. MapT::find). In that case it will have the time complexity of
* that. In case of a "map-like" (e.g. vector<tuple<K, V>>) it will be O(N).
*/
template<typename FromT, typename MapT, typename = std::enable_if_t<std::is_same_v<FromT, key_t<MapT>>>>
auto mapLookupTo(FromT keyObj, const MapT& map) -> std::optional<mapped_t<MapT>>
{
if constexpr (is_map_t<MapT>) {
if (const auto& it = map.find(keyObj); it != map.end()) {
return it->second;
template<typename T>
using key_t = typename map_t_helper<T>::key_type;

template<typename T>
using mapped_t = typename map_t_helper<T>::mapped_type;

/**
* Find the mapped-to object in a map provided a key object
*
* NOTE: This will use a potentially more efficient lookup for actual map
* types (i.e. MapT::find). In that case it will have the time complexity of
* that. In case of a "map-like" (e.g. vector<tuple<K, V>>) it will be O(N).
*/
template<typename FromT, typename MapT, typename = std::enable_if_t<std::is_same_v<FromT, key_t<MapT>>>>
auto mapLookupTo(FromT keyObj, const MapT& map) -> std::optional<mapped_t<MapT>>
{
if constexpr (is_map_t<MapT>) {
if (const auto& it = map.find(keyObj); it != map.end()) {
return it->second;
}
}
else {
if (const auto& it = std::find_if(
map.begin(), map.end(), [&keyObj](const auto& mapElem) { return std::get<0>(mapElem) == keyObj; });
it != map.end()) {
return std::get<1>(*it);
}
}

return std::nullopt;
}
else {

/**
* Find the mapped-from (or key object) in a "map" provided a mapped-to object
*
* NOTE: This will always loop over potentially all elements in the provided
* map, so it is definitely O(N) regardless of the provided map type
*/
template<typename ToT, typename MapT, typename = std::enable_if_t<std::is_same_v<ToT, mapped_t<MapT>>>>
auto mapLookupFrom(ToT mappedObj, const MapT& map) -> std::optional<key_t<MapT>>
{
// In this case we cannot use a potential find method for an actual map, but
// looping over the map and doing the actual comparison will work
if (const auto& it = std::find_if(
map.begin(), map.end(), [&keyObj](const auto& mapElem) { return std::get<0>(mapElem) == keyObj; });
map.begin(), map.end(), [&mappedObj](const auto& mapElem) { return std::get<1>(mapElem) == mappedObj; });
it != map.end()) {
return std::get<1>(*it);
return std::get<0>(*it);
}
}

return std::nullopt;
}

/**
* Find the mapped-from (or key object) in a "map" provided a mapped-to object
*
* NOTE: This will always loop over potentially all elements in the provided
* map, so it is definitely O(N) regardless of the provided map type
*/
template<typename ToT, typename MapT, typename = std::enable_if_t<std::is_same_v<ToT, mapped_t<MapT>>>>
auto mapLookupFrom(ToT mappedObj, const MapT& map) -> std::optional<key_t<MapT>>
{
// In this case we cannot use a potential find method for an actual map, but
// looping over the map and doing the actual comparison will work
if (const auto& it = std::find_if(
map.begin(), map.end(), [&mappedObj](const auto& mapElem) { return std::get<1>(mapElem) == mappedObj; });
it != map.end()) {
return std::get<0>(*it);
return std::nullopt;
}
} // namespace detail

template<typename K, typename V>
using MapT = std::unordered_map<K, V>;

return std::nullopt;
}
template<typename K, typename V>
using VecMapT = std::vector<std::tuple<K, V>>;

} // namespace k4EDM4hep2LcioConv::detail
} // namespace k4EDM4hep2LcioConv

#endif // K4EDM4HEP2LCIOCONV_MAPPINGUTILS_H
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef K4EDM4HEP2LCIOCONV_H
#define K4EDM4HEP2LCIOCONV_H

#include <cassert>
#include "k4EDM4hep2LcioConv/MappingUtils.h"

// EDM4hep
#include <edm4hep/CaloHitContributionCollection.h>
Expand Down Expand Up @@ -57,8 +57,10 @@ namespace edm4hep {
#include <UTIL/CellIDEncoder.h>
#include <lcio.h>

#include <cassert>

template<typename T1, typename T2>
using vec_pair = std::vector<std::pair<T1, T2>>;
using vec_pair = k4EDM4hep2LcioConv::VecMapT<T1, T2>;

struct CollectionsPairVectors {
vec_pair<lcio::TrackImpl*, edm4hep::Track> tracks;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#ifndef K4EDM4HEP2LCIOCONV_K4LCIO2EDM4HEPCONV_H
#define K4EDM4HEP2LCIOCONV_K4LCIO2EDM4HEPCONV_H

#include "MappingUtils.h"
#include "k4EDM4hep2LcioConv/MappingUtils.h"

// EDM4hep
#include "edm4hep/CaloHitContributionCollection.h"
Expand Down Expand Up @@ -62,7 +62,7 @@

namespace LCIO2EDM4hepConv {
template<typename LcioT, typename EdmT>
using TypeMapT = std::unordered_map<LcioT, EdmT>;
using TypeMapT = k4EDM4hep2LcioConv::MapT<LcioT, EdmT>;

/**
* Maping holding all the original and converted objects in a 1:1 mapping in a
Expand Down

0 comments on commit 44b37f9

Please sign in to comment.