Skip to content

Commit

Permalink
Improve generated interface function name to obtain the actual type (#…
Browse files Browse the repository at this point in the history
…595)

* Improve interface function name

getValue mixes a bit too much implementation detail into the interface.
Additionally, as is very short and reads well in this context.

* Fix occurences of getValue in tests

* Update documentation
  • Loading branch information
tmadlener authored Jun 4, 2024
1 parent a4e684f commit 6a6d954
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 10 deletions.
4 changes: 2 additions & 2 deletions doc/datamodel_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ bool same = (energyType == cluster); // <-- true (comparisons work as expected)
bool isCluster = energyType.isA<ExampleCluster>(); // <-- true
bool isHit = energyType.isA<ExampleHit>(); // <-- false
auto newCluster = energyType.getValue<ExampleCluster>(); // <-- "cast back" to original type
auto newCluster = energyType.as<ExampleCluster>(); // <-- "cast back" to original type
// "Casting" only works if the types match. Otherwise there will be an exception
auto newHit = energyType.getValue<ExampleHit>(); // <-- exception
auto newHit = energyType.as<ExampleHit>(); // <-- exception
```

## Global options
Expand Down
10 changes: 8 additions & 2 deletions python/templates/Interface.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -131,16 +131,22 @@ public:

/// Get the contained value as the concrete type it was put in. This will
/// throw a std::runtime_error if T is not the type of the currently held
/// value. Use holds to check beforehand if necessary template<typename T>
/// value. Use isA to check beforehand if necessary
template<typename T>
T getValue() const {
T as() const {
if (!isA<T>()) {
throw std::runtime_error("Cannot get value as object currently holds another type");
}
// We can safely cast here since we check types before
return static_cast<Model<T>*>(m_self.get())->m_value;
}

template<typename T>
[[deprecated("Use 'as' instead.")]]
T getValue() const {
return as<T>();
}

friend bool operator==(const {{ class.bare_type }}& lhs, const {{ class.bare_type }}& rhs) {
return lhs.m_self->equal(rhs.m_self.get());
}
Expand Down
12 changes: 6 additions & 6 deletions tests/unittests/interface_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,14 @@ TEST_CASE("InterfaceType from immutable", "[interface-types][basics]") {
WrapperT wrapper{hit};
REQUIRE(wrapper.isA<ExampleHit>());
REQUIRE_FALSE(wrapper.isA<ExampleCluster>());
REQUIRE(wrapper.getValue<ExampleHit>() == hit);
REQUIRE(wrapper.as<ExampleHit>() == hit);
REQUIRE(wrapper == hit);

ExampleCluster cluster{};
wrapper = cluster;
REQUIRE(wrapper.isA<ExampleCluster>());
REQUIRE(wrapper.getValue<ExampleCluster>() == cluster);
REQUIRE_THROWS_AS(wrapper.getValue<ExampleHit>(), std::runtime_error);
REQUIRE(wrapper.as<ExampleCluster>() == cluster);
REQUIRE_THROWS_AS(wrapper.as<ExampleHit>(), std::runtime_error);
REQUIRE(wrapper != hit);
}

Expand All @@ -91,7 +91,7 @@ TEST_CASE("InterfaceType from mutable", "[interface-types][basics]") {
WrapperT wrapper{hit};
REQUIRE(wrapper.isA<ExampleHit>());
REQUIRE_FALSE(wrapper.isA<ExampleCluster>());
REQUIRE(wrapper.getValue<ExampleHit>() == hit);
REQUIRE(wrapper.as<ExampleHit>() == hit);
REQUIRE(wrapper == hit);
// Comparison also work against the immutable classes
ExampleHit immutableHit = hit;
Expand All @@ -100,8 +100,8 @@ TEST_CASE("InterfaceType from mutable", "[interface-types][basics]") {
MutableExampleCluster cluster{};
wrapper = cluster;
REQUIRE(wrapper.isA<ExampleCluster>());
REQUIRE(wrapper.getValue<ExampleCluster>() == cluster);
REQUIRE_THROWS_AS(wrapper.getValue<ExampleHit>(), std::runtime_error);
REQUIRE(wrapper.as<ExampleCluster>() == cluster);
REQUIRE_THROWS_AS(wrapper.as<ExampleHit>(), std::runtime_error);
REQUIRE(wrapper != hit);
}

Expand Down

0 comments on commit 6a6d954

Please sign in to comment.