diff --git a/CMakeLists.txt b/CMakeLists.txt index 25167f5..a2fe5ef 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -252,6 +252,7 @@ if(XYZ_PROTOCOL_IS_NOT_SUBPROJECT) protocol.h protocol_reflection.hxx interface_A.h + interface_B.h interface_C.h protocol_reflection_smoke_test.cc) target_compile_options(protocol_reflection_smoke_test diff --git a/protocol_reflection_detail/naming.hxx b/protocol_reflection_detail/naming.hxx index 4e60c2c..ba36309 100644 --- a/protocol_reflection_detail/naming.hxx +++ b/protocol_reflection_detail/naming.hxx @@ -57,14 +57,15 @@ constexpr std::string identifier_safe_string(std::string_view s) { } // The generated vtable-entry name for a reflected member function or data -// member, found by name. Operators, which have no identifier_of, need -// separate handling. Deliberately identifier-only, not signature-qualified: -// this names a forwarder's single public-facing data member (forwarders.hxx), -// which must stay callable as e.g. `.compute(...)` regardless of how many -// overloads `compute` has. Every overload of the same name shares this -// name on purpose. +// member: `member`'s own identifier, verbatim, not escaped, since a named +// member's identifier is already a valid C++ identifier. Operators, which +// have no identifier_of, need separate handling. This is what a forwarder's +// single public-facing data member is called (forwarders.hxx); it must +// stay callable as e.g. `.compute(...)` regardless of how many overloads +// `compute` has, so every overload of the same name shares this name on +// purpose. consteval std::string vtable_entry_name(std::meta::info member) { - return identifier_safe_string(std::meta::identifier_of(member)); + return std::string(std::meta::identifier_of(member)); } // A generated vtable struct's entry name for `member`, unique per exact diff --git a/protocol_reflection_detail/naming_test.cc b/protocol_reflection_detail/naming_test.cc index d7cfe02..f071025 100644 --- a/protocol_reflection_detail/naming_test.cc +++ b/protocol_reflection_detail/naming_test.cc @@ -74,14 +74,15 @@ struct Fixture { void set_value(int) {} }; -TEST(VtableEntryName, NamesAnOrdinaryMemberByItsIdentifier) { +TEST(VtableEntryName, NamesAnOrdinaryMemberByItsExactIdentifier) { + // Unlike vtable_slot_name's internal, escaped names below. constexpr const char* value_name = std::define_static_string(vtable_entry_name(^^Fixture::value)); constexpr const char* set_value_name = std::define_static_string(vtable_entry_name(^^Fixture::set_value)); EXPECT_STREQ(value_name, "value"); - EXPECT_STREQ(set_value_name, "set_5fvalue"); + EXPECT_STREQ(set_value_name, "set_value"); } struct Overloaded { diff --git a/protocol_reflection_smoke_test.cc b/protocol_reflection_smoke_test.cc index c76d8e6..2be0d14 100644 --- a/protocol_reflection_smoke_test.cc +++ b/protocol_reflection_smoke_test.cc @@ -24,8 +24,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include #include #include +#include #include "interface_A.h" +#include "interface_B.h" #include "interface_C.h" #include "protocol.h" @@ -112,4 +114,28 @@ TEST(ProtocolReflectionSmoke, DispatchesEachOverloadOfCToTheMatchingCandidate) { EXPECT_EQ(c.compute(std::string("ab")), "abab"); } +// Interface B: plain, non-overloaded members. No new protocol_reflection.hxx +// machinery. +struct BLike { + std::vector results_; + bool ready_ = false; + + void process(const std::string& input) { + results_.push_back(static_cast(input.length())); + ready_ = true; + } + + std::vector get_results() const { return results_; } + + bool is_ready() const { return ready_; } +}; + +TEST(ProtocolReflectionSmoke, DispatchesAllThreeMembersOfB) { + xyz::protocol b(std::in_place_type); + EXPECT_FALSE(b.is_ready()); + b.process("hello"); + EXPECT_TRUE(b.is_ready()); + EXPECT_EQ(b.get_results(), (std::vector{5})); +} + } // namespace