Skip to content

Commit e362cdb

Browse files
committed
Add range constructor to generated collections
1 parent caa7f28 commit e362cdb

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
@@ -666,6 +666,33 @@ TEST_CASE("Collection size and empty", "[basics][collections]") {
666666
REQUIRE(coll.size() == 2u);
667667
}
668668

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

0 commit comments

Comments
 (0)