diff --git a/CMakeLists.txt b/CMakeLists.txt index d2fe59e..9e5ea96 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -251,6 +251,7 @@ if(XYZ_PROTOCOL_IS_NOT_SUBPROJECT) FILES protocol.h protocol_reflection.hxx + interface_A.h protocol_reflection_smoke_test.cc) target_compile_options(protocol_reflection_smoke_test PRIVATE -freflection) diff --git a/protocol_reflection_smoke_test.cc b/protocol_reflection_smoke_test.cc index 2e0e2c0..54e0cac 100644 --- a/protocol_reflection_smoke_test.cc +++ b/protocol_reflection_smoke_test.cc @@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include +#include "interface_A.h" #include "protocol.h" namespace { @@ -66,4 +67,28 @@ TEST(ProtocolReflectionSmoke, NonConformingTypeFailsToCompile) { std::in_place_type_t>); } +// name() is const and noexcept; count() is not. The vtable already erases +// every entry through void* uniformly regardless of member constness, so +// this proves mixed const/non-const dispatch works. +struct ALike { + std::string name_ = "ALike"; + int count_ = 0; + + std::string_view name() const noexcept { return name_; } + + int count() { return ++count_; } +}; + +TEST(ProtocolReflectionSmoke, DispatchesBothConstAndNonConstMembersOfA) { + xyz::protocol a(std::in_place_type); + EXPECT_EQ(a.name(), "ALike"); + EXPECT_EQ(a.count(), 1); + EXPECT_EQ(a.count(), 2); +} + +TEST(ProtocolReflectionSmoke, ANameIsActuallyNoexcept) { + xyz::protocol a(std::in_place_type); + static_assert(noexcept(a.name())); +} + } // namespace