Skip to content

Commit e78406e

Browse files
authored
Merge pull request #45777 from Dr15Jones/concepts_RefToBase
Use C++ concepts in RefToBase
2 parents 7f86010 + 58c2872 commit e78406e

File tree

4 files changed

+110
-106
lines changed

4 files changed

+110
-106
lines changed

DataFormats/Common/interface/RefToBase.h

Lines changed: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ namespace edm {
9999
size_t key() const;
100100

101101
template <class REF>
102+
requires requires {
103+
typename REF::value_type;
104+
requires std::is_same_v<T, typename REF::value_type> or std::is_base_of_v<T, typename REF::value_type> or
105+
std::is_base_of_v<typename REF::value_type, T>;
106+
}
102107
REF castTo() const;
103108

104109
bool isNull() const;
@@ -228,43 +233,20 @@ namespace edm {
228233
return holder_->key();
229234
}
230235

231-
namespace {
232-
// If the template parameters are classes or structs they should be
233-
// related by inheritance, otherwise they should be the same type.
234-
template <typename T, typename U>
235-
typename std::enable_if<std::is_class<T>::value>::type checkTypeCompatibility() {
236-
static_assert(std::is_base_of<T, U>::value || std::is_base_of<U, T>::value,
237-
"RefToBase::castTo error element types are not related by inheritance");
238-
}
239-
240-
template <typename T, typename U>
241-
typename std::enable_if<!std::is_class<T>::value>::type checkTypeCompatibility() {
242-
static_assert(std::is_same<T, U>::value, "RefToBase::castTo error non-class element types are not the same");
243-
}
244-
245-
// Convert the pointer types, use dynamic_cast if they are classes
246-
template <typename T, typename OUT>
247-
typename std::enable_if<std::is_class<T>::value, OUT const*>::type convertTo(T const* t) {
248-
return dynamic_cast<OUT const*>(t);
249-
}
250-
251-
template <typename T, typename OUT>
252-
typename std::enable_if<!std::is_class<T>::value, OUT const*>::type convertTo(T const* t) {
253-
return t;
254-
}
255-
} // namespace
256-
257236
template <class T>
258237
template <class REF>
238+
requires requires {
239+
typename REF::value_type;
240+
requires std::is_same_v<T, typename REF::value_type> or std::is_base_of_v<T, typename REF::value_type> or
241+
std::is_base_of_v<typename REF::value_type, T>;
242+
}
259243
REF RefToBase<T>::castTo() const {
260244
if (!holder_) {
261245
Exception::throwThis(errors::InvalidReference,
262246
"attempting to cast a null RefToBase;\n"
263247
"You should check for nullity before casting.");
264248
}
265249

266-
checkTypeCompatibility<T, typename REF::value_type>();
267-
268250
// If REF is type edm::Ref<C,T,F>, then it is impossible to
269251
// check the container type C here. We just have to assume
270252
// that the caller provided the correct type.
@@ -278,7 +260,12 @@ namespace edm {
278260
if (value == nullptr) {
279261
return REF(id());
280262
}
281-
typename REF::value_type const* newValue = convertTo<T, typename REF::value_type>(value);
263+
typename REF::value_type const* newValue;
264+
if constexpr (std::is_same_v<T, typename REF::value_type> or std::is_base_of_v<typename REF::value_type, T>) {
265+
newValue = value;
266+
} else {
267+
newValue = dynamic_cast<typename REF::value_type const*>(value);
268+
}
282269
if (newValue) {
283270
return REF(id(), newValue, key(), isTransient());
284271
}

DataFormats/Common/test/BuildFile.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@
1111

1212
<test name="TestTriggerResultsFormat" command="TestTriggerResultsFormat.sh"/>
1313

14-
<bin name="testDataFormatsCommon" file="testRunner.cpp,testOwnVector.cc,testOneToOneAssociation.cc,testValueMap.cc,testOneToManyAssociation.cc,testAssociationVector.cc,testAssociationNew.cc,testValueMapNew.cc,testSortedCollection.cc,testRangeMap.cc,ref_t.cppunit.cc,DetSetRefVector_t.cppunit.cc,reftobase_t.cppunit.cc,reftobasevector_t.cppunit.cc,cloningptr_t.cppunit.cc,ptr_t.cppunit.cc,ptrvector_t.cppunit.cc,containermask_t.cppunit.cc,reftobaseprod_t.cppunit.cc,handle_t.cppunit.cc">
14+
<bin name="testDataFormatsCommon" file="testRunner.cpp,testOwnVector.cc,testOneToOneAssociation.cc,testValueMap.cc,testOneToManyAssociation.cc,testAssociationVector.cc,testAssociationNew.cc,testValueMapNew.cc,testSortedCollection.cc,testRangeMap.cc,ref_t.cppunit.cc,DetSetRefVector_t.cppunit.cc,reftobasevector_t.cppunit.cc,cloningptr_t.cppunit.cc,ptr_t.cppunit.cc,ptrvector_t.cppunit.cc,containermask_t.cppunit.cc,reftobaseprod_t.cppunit.cc,handle_t.cppunit.cc">
1515
</bin>
1616

17-
<bin name="testDataFormatsCommonCatch2" file="DetSetVector_t.cpp,exDSTV.cpp,exTrie.cpp,OwnVector_t.cpp,Wrapper_t.cpp,testBoostRange.cpp">
17+
<bin name="testDataFormatsCommonCatch2" file="DetSetVector_t.cpp,exDSTV.cpp,exTrie.cpp,OwnVector_t.cpp,Wrapper_t.cpp,testBoostRange.cpp,reftobase_t.cpp,">
1818
<use name="catch2"/>
1919
</bin>
2020

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
#include "catch.hpp"
2+
3+
#include "DataFormats/Common/interface/RefToBase.h"
4+
#include "DataFormats/Common/interface/Ref.h"
5+
#include "DataFormats/Common/interface/TestHandle.h"
6+
7+
#include <vector>
8+
9+
namespace testreftobase {
10+
struct Base {
11+
virtual ~Base() {}
12+
virtual int val() const = 0;
13+
};
14+
15+
struct Inherit1 : public Base {
16+
virtual int val() const { return 1; }
17+
};
18+
struct Inherit2 : public Base {
19+
virtual int val() const { return 2; }
20+
};
21+
} // namespace testreftobase
22+
23+
using namespace testreftobase;
24+
25+
TEST_CASE("test RefToBase", "[RefToBase]") {
26+
SECTION("Class type") {
27+
using namespace edm;
28+
29+
std::vector<Inherit1> v1(2, Inherit1());
30+
31+
TestHandle<std::vector<Inherit1> > h1(&v1, ProductID(1, 1));
32+
Ref<std::vector<Inherit1> > r1(h1, 1);
33+
RefToBase<Base> b1(r1);
34+
35+
SECTION("Value check") {
36+
CHECK(&(*b1) == static_cast<Base*>(&(v1[1])));
37+
CHECK(b1.operator->() == b1.get());
38+
CHECK(b1.get() == static_cast<Base*>(&(v1[1])));
39+
CHECK(b1.id() == ProductID(1, 1));
40+
}
41+
SECTION("Copy constructor") {
42+
//copy constructor
43+
RefToBase<Base> b2(b1);
44+
CHECK(&(*b2) == static_cast<Base*>(&(v1[1])));
45+
CHECK(b2.id() == b1.id());
46+
}
47+
48+
SECTION("operator=") {
49+
//operator=
50+
RefToBase<Base> b3;
51+
CHECK(b3.isNull());
52+
CHECK(!(b3.isNonnull()));
53+
CHECK(!b3);
54+
b3 = b1;
55+
CHECK(&(*b3) == static_cast<Base*>(&(v1[1])));
56+
CHECK(b3.id() == b1.id());
57+
CHECK(!(b3.isNull()));
58+
CHECK(b3.isNonnull());
59+
CHECK(!(!b3));
60+
}
61+
62+
SECTION("castTo inheriting type") { CHECK(b1.castTo<Ref<std::vector<Inherit1> > >() == r1); }
63+
SECTION("castTo incorrect inherting type") {
64+
CHECK_THROWS_AS(b1.castTo<Ref<std::vector<Inherit2> > >(), cms::Exception);
65+
}
66+
/*
67+
Uncomment to test compile time failure
68+
SECTION("castTo unrelated type") {
69+
b1.castTo<Ref<std::vector<std::string> > >();
70+
} */
71+
}
72+
73+
SECTION("builtin type") {
74+
using namespace edm;
75+
std::vector<int> v1(2, 3);
76+
77+
TestHandle<std::vector<int> > h1(&v1, ProductID(1, 1));
78+
Ref<std::vector<int> > r1(h1, 1);
79+
RefToBase<int> b1(r1);
80+
81+
SECTION("Value check") {
82+
CHECK(&(*b1) == &v1[1]);
83+
CHECK(b1.operator->() == b1.get());
84+
CHECK(b1.get() == (&(v1[1])));
85+
CHECK(b1.id() == ProductID(1, 1));
86+
}
87+
SECTION("castTo Ref") { CHECK(b1.castTo<Ref<std::vector<int> > >() == r1); }
88+
/* uncomment to test compile time failure
89+
SECTION("bad castTo Ref") { b1.castTo<Ref<std::vector<double> > >(); }
90+
*/
91+
}
92+
}

DataFormats/Common/test/reftobase_t.cppunit.cc

Lines changed: 0 additions & 75 deletions
This file was deleted.

0 commit comments

Comments
 (0)