Skip to content

Commit d617722

Browse files
committed
Add range constructor to generated collections
1 parent a81809b commit d617722

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

python/templates/Collection.h.jinja2

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "podio/ICollectionProvider.h"
1717
#include "podio/CollectionBase.h"
1818
#include "podio/detail/Pythonizations.h"
19+
#include "podio/utilities/TypeHelpers.h"
1920

2021
#if defined(PODIO_JSON_OUTPUT) && !defined(__CLING__)
2122
#include "nlohmann/json_fwd.hpp"
@@ -64,6 +65,11 @@ public:
6465

6566
~{{ class.bare_type }}Collection() override;
6667

68+
/// Construct a {{ class.bare_type }} collection from a range of mutable or
69+
/// immutable handles
70+
template<podio::detail::RangeConvertibleTo<value_type> R>
71+
static {{ class.bare_type }}Collection from(R&& range);
72+
6773
constexpr static std::string_view typeName = "{{ (class | string ).strip(':') + "Collection" }}";
6874
constexpr static std::string_view valueTypeName = "{{ (class | string ).strip(':') }}";
6975
constexpr static std::string_view dataTypeName = "{{ ( class | string ).strip(':') }}Data";
@@ -236,6 +242,21 @@ Mutable{{ class.bare_type }} {{ class.bare_type }}Collection::create(Args&&... a
236242
return Mutable{{ class.bare_type }}(podio::utils::MaybeSharedPtr(obj));
237243
}
238244

245+
template<podio::detail::RangeConvertibleTo<{{ class.bare_type }}Collection::value_type> R>
246+
{{ class.bare_type }}Collection {{ class.bare_type }}Collection::from(R&& range) {
247+
{{ class.bare_type }}Collection coll;
248+
if constexpr (podio::detail::RangeOf<R, value_type>) {
249+
coll.setSubsetCollection();
250+
}
251+
252+
for (auto elem : range) {
253+
coll.push_back(elem);
254+
}
255+
256+
return coll;
257+
}
258+
259+
239260
#if defined(PODIO_JSON_OUTPUT) && !defined(__CLING__)
240261
void to_json(nlohmann::json& j, const {{ class.bare_type }}Collection& collection);
241262
#endif

tests/unittests/unittest.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,33 @@ TEST_CASE("Collection size and empty", "[basics][collections]") {
664664
REQUIRE(coll.size() == 2u);
665665
}
666666

667+
TEST_CASE("Collection construction from range", "[basics][collections]") {
668+
std::vector<MutableExampleCluster> clusters(10);
669+
auto clusterColl = ExampleClusterCollection::from(clusters);
670+
REQUIRE_FALSE(clusterColl.isSubsetCollection());
671+
REQUIRE(clusterColl.size() == clusters.size());
672+
for (size_t i = 0; i < clusters.size(); ++i) {
673+
REQUIRE(clusterColl[i] == clusters[i]);
674+
}
675+
676+
const auto otherClusterColl = ExampleClusterCollection::from(std::as_const(clusterColl));
677+
REQUIRE(otherClusterColl.isSubsetCollection());
678+
REQUIRE(otherClusterColl.size() == clusterColl.size());
679+
for (size_t i = 0; i < clusters.size(); ++i) {
680+
REQUIRE(otherClusterColl[i] == clusterColl[i]);
681+
}
682+
683+
// Cannot construct a collection from a range of unowned immutable handles
684+
REQUIRE_THROWS_AS(ExampleClusterCollection::from(std::vector<ExampleCluster>(10)), std::invalid_argument);
685+
686+
for (const auto& cluster : clusterColl) {
687+
REQUIRE(cluster.id().index != podio::ObjectID::untracked);
688+
}
689+
// Cannot construct a collection from a range of mutable handles that are
690+
// already owned
691+
REQUIRE_THROWS_AS(ExampleClusterCollection::from(clusters), std::invalid_argument);
692+
}
693+
667694
TEST_CASE("const correct indexed access to const collections", "[const-correctness]") {
668695
STATIC_REQUIRE(std::is_same_v<decltype(std::declval<const ExampleClusterCollection>()[0]),
669696
ExampleCluster>); // const collections should only have indexed access to mutable

0 commit comments

Comments
 (0)