From 92be0bd4a6c50cdd0edb1963323ccbd178c0f608 Mon Sep 17 00:00:00 2001 From: Michael Sherman Date: Tue, 10 Aug 2021 18:24:09 -0700 Subject: [PATCH] Makes ValidateCreatedForThisSystem() inline-able and moves it to SystemBase (#15595) --- common/identifier.h | 10 ++++ common/test/identifier_test.cc | 21 +++++++ systems/framework/diagram.cc | 8 +-- systems/framework/system.cc | 2 +- systems/framework/system.h | 19 ------- systems/framework/system_base.cc | 14 +++++ systems/framework/system_base.h | 55 ++++++++++++++++++- .../framework/system_compatibility_doxygen.h | 10 ++-- systems/framework/system_output.h | 8 +-- systems/framework/test/system_base_test.cc | 37 ++++++++++++- 10 files changed, 147 insertions(+), 37 deletions(-) diff --git a/common/identifier.h b/common/identifier.h index 4eca8e9d1c47..bec41960e9d6 100644 --- a/common/identifier.h +++ b/common/identifier.h @@ -200,6 +200,16 @@ class Identifier { hash_append(hasher, i.value_); } + /** (Internal use only) Compares this possibly-invalid Identifier with one + that is known to be valid and returns `false` if they don't match. It is an + error if `valid_id` is not actually valid, and that is strictly enforced in + Debug builds. However, it is not an error if `this` id is invalid; that + results in a `false` return. This method can be faster than testing + separately for validity and equality. */ + bool is_same_as_valid_id(Identifier valid_id) const { + return value_ == valid_id.get_value(); + } + protected: // Instantiates an identifier from the underlying representation type. explicit Identifier(int64_t val) : value_(val) {} diff --git a/common/test/identifier_test.cc b/common/test/identifier_test.cc index 1bf0fd851fae..006a06fc13d7 100644 --- a/common/test/identifier_test.cc +++ b/common/test/identifier_test.cc @@ -72,6 +72,17 @@ TEST_F(IdentifierTests, AssignmentAndComparison) { EXPECT_TRUE(temp == a3_); } +// Check the specialized internal-use compare that can be used on an invalid +// Identifier. +TEST_F(IdentifierTests, InvalidOrSameComparison) { + AId same_as_a1 = a1_; + EXPECT_TRUE(same_as_a1.is_same_as_valid_id(a1_)); + EXPECT_FALSE(a1_.is_same_as_valid_id(a2_)); + + AId invalid; + EXPECT_FALSE(invalid.is_same_as_valid_id(a1_)); +} + // Confirms that ids are configured to serve as unique keys in // STL containers. TEST_F(IdentifierTests, ServeAsMapKey) { @@ -234,6 +245,16 @@ TEST_F(IdentifierTests, InvalidInequalityCompare) { DRAKE_EXPECT_THROWS_MESSAGE(unused(invalid != a1_), ".*is_valid.*failed.*"); } +// Comparison of invalid ids is an error. +TEST_F(IdentifierTests, BadInvalidOrSameComparison) { + if (kDrakeAssertIsDisarmed) { + return; + } + AId invalid; + DRAKE_EXPECT_THROWS_MESSAGE(unused(a1_.is_same_as_valid_id(invalid)), + ".*is_valid.*failed.*"); +} + // Hashing an invalid id is *not* an error. TEST_F(IdentifierTests, InvalidHash) { if (kDrakeAssertIsDisarmed) { diff --git a/systems/framework/diagram.cc b/systems/framework/diagram.cc index 774040d50464..75f5c4529f72 100644 --- a/systems/framework/diagram.cc +++ b/systems/framework/diagram.cc @@ -366,7 +366,7 @@ template const ContinuousState& Diagram::GetSubsystemDerivatives( const System& subsystem, const ContinuousState& derivatives) const { - this->ValidateCreatedForThisSystem(&derivatives); + this->ValidateCreatedForThisSystem(derivatives); auto diagram_derivatives = dynamic_cast*>(&derivatives); DRAKE_DEMAND(diagram_derivatives != nullptr); @@ -378,7 +378,7 @@ template const DiscreteValues& Diagram::GetSubsystemDiscreteValues( const System& subsystem, const DiscreteValues& discrete_values) const { - this->ValidateCreatedForThisSystem(&discrete_values); + this->ValidateCreatedForThisSystem(discrete_values); auto diagram_discrete_state = dynamic_cast*>(&discrete_values); DRAKE_DEMAND(diagram_discrete_state != nullptr); @@ -390,7 +390,7 @@ template const CompositeEventCollection& Diagram::GetSubsystemCompositeEventCollection(const System& subsystem, const CompositeEventCollection& events) const { - this->ValidateCreatedForThisSystem(&events); + this->ValidateCreatedForThisSystem(events); auto ret = DoGetTargetSystemCompositeEventCollection(subsystem, &events); DRAKE_DEMAND(ret != nullptr); return *ret; @@ -427,7 +427,7 @@ State& Diagram::GetMutableSubsystemState(const System& subsystem, template const State& Diagram::GetSubsystemState(const System& subsystem, const State& state) const { - this->ValidateCreatedForThisSystem(&state); + this->ValidateCreatedForThisSystem(state); auto ret = DoGetTargetSystemState(subsystem, &state); DRAKE_DEMAND(ret != nullptr); return *ret; diff --git a/systems/framework/system.cc b/systems/framework/system.cc index c2b23a4baf9f..6acd51aa8a66 100644 --- a/systems/framework/system.cc +++ b/systems/framework/system.cc @@ -274,7 +274,7 @@ void System::CalcImplicitTimeDerivativesResidual( this->implicit_time_derivatives_residual_size(), residual->size())); } ValidateContext(context); - ValidateCreatedForThisSystem(&proposed_derivatives); + ValidateCreatedForThisSystem(proposed_derivatives); DoCalcImplicitTimeDerivativesResidual(context, proposed_derivatives, residual); } diff --git a/systems/framework/system.h b/systems/framework/system.h index bd8e47426dda..1738ae8f49b8 100644 --- a/systems/framework/system.h +++ b/systems/framework/system.h @@ -1693,25 +1693,6 @@ class System : public SystemBase { return system_scalar_converter_; } - /** Checks whether the given object was created for this system. - @note This method is sufficiently fast for performance sensitive code. */ - template