Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 8 additions & 7 deletions protocol_reflection_detail/naming.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions protocol_reflection_detail/naming_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
26 changes: 26 additions & 0 deletions protocol_reflection_smoke_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <string>
#include <string_view>
#include <type_traits>
#include <vector>

#include "interface_A.h"
#include "interface_B.h"
#include "interface_C.h"
#include "protocol.h"

Expand Down Expand Up @@ -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<int> results_;
bool ready_ = false;

void process(const std::string& input) {
results_.push_back(static_cast<int>(input.length()));
ready_ = true;
}

std::vector<int> get_results() const { return results_; }

bool is_ready() const { return ready_; }
};

TEST(ProtocolReflectionSmoke, DispatchesAllThreeMembersOfB) {
xyz::protocol<xyz::B> b(std::in_place_type<BLike>);
EXPECT_FALSE(b.is_ready());
b.process("hello");
EXPECT_TRUE(b.is_ready());
EXPECT_EQ(b.get_results(), (std::vector<int>{5}));
}

} // namespace
Loading