Skip to content

Commit 263b661

Browse files
committed
mock_mem_fn can accept a real member pointer
1 parent f4807f8 commit 263b661

File tree

2 files changed

+53
-8
lines changed

2 files changed

+53
-8
lines changed

include/peacalm/luaw.h

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,12 @@ class luaw {
246246
template <typename T, typename = void>
247247
struct registrar;
248248

249-
// A callable object adapter, which bahaves like the result of std::mem_fn.
250-
// The origin first argument should be reference or raw pointer,
251-
// then this object can accept reference, raw pointer, and also smart pointers
252-
// (std::shared_ptr and std::unique_ptr) as the first argument to call the
253-
// origin callable object.
254-
template <typename T>
249+
// Mock std::mem_fn by a function or callable object whose first argument
250+
// must be raw pointer of a class.
251+
// Then can call this class by reference, raw pointer or smart pointers
252+
// (std::shared_ptr and std::unique_ptr) of the class.
253+
// Also can accept a real member pointer, then it is just like std::mem_fn.
254+
template <typename T, typename = void>
255255
class mock_mem_fn;
256256

257257
// Mock non-member to be a class's member.
@@ -4290,9 +4290,12 @@ auto retrieve_underlying_ptr(T&& t) {
42904290

42914291
} // namespace luaw_detail
42924292

4293-
// The first argument of CallableObject must be pointer, and could be `auto*`.
4293+
// The first argument of CallableObject must be raw pointer, and could be
4294+
// `auto*` (in lambda).
42944295
template <typename CallableObject>
4295-
class luaw::mock_mem_fn {
4296+
class luaw::mock_mem_fn<
4297+
CallableObject,
4298+
std::enable_if_t<!std::is_member_pointer<CallableObject>::value>> {
42964299
CallableObject o;
42974300

42984301
public:
@@ -4305,6 +4308,22 @@ class luaw::mock_mem_fn {
43054308
}
43064309
};
43074310

4311+
template <typename MemberPointer>
4312+
class luaw::mock_mem_fn<
4313+
MemberPointer,
4314+
std::enable_if_t<std::is_member_pointer<MemberPointer>::value>> {
4315+
decltype(std::mem_fn(static_cast<MemberPointer>(nullptr))) o;
4316+
4317+
public:
4318+
mock_mem_fn(MemberPointer p) : o(std::mem_fn(p)) {}
4319+
4320+
template <typename FirstArg, typename... Args>
4321+
decltype(auto) operator()(FirstArg&& f, Args&&... args) const {
4322+
return o(luaw_detail::retrieve_underlying_ptr(std::forward<FirstArg>(f)),
4323+
std::forward<Args>(args)...);
4324+
};
4325+
};
4326+
43084327
//////////////////// static_mem_fn impl ////////////////////////////////////////
43094328

43104329
// specialize for C function pointer

test/unit_test/register_member.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1861,4 +1861,30 @@ TEST(register_member, get_object_created_by_lua) {
18611861
EXPECT_EQ(a.ci, 1);
18621862
}
18631863

1864+
TEST(register_member, nonconst_as_const_member) {
1865+
luaw l;
1866+
l.register_member<const int Obj::*>("i", &Obj::i);
1867+
l.register_member("i2", &Obj::i);
1868+
1869+
l.set("o", Obj{});
1870+
EXPECT_EQ(l.eval<int>("return o.i"), 1);
1871+
EXPECT_EQ(l.eval<int>("return o.i2"), 1);
1872+
1873+
EXPECT_EQ(l.dostring("o.i2 = 2"), LUA_OK);
1874+
EXPECT_NE(l.dostring("o.i = 2"), LUA_OK);
1875+
l.log_error_out();
1876+
}
1877+
1878+
TEST(register_member, change_member_function_type) {
1879+
luaw l;
1880+
l.register_member("i", &Obj::i);
1881+
l.register_member("geti", &Obj::geti);
1882+
l.register_member<bool (Obj::*)() const>("getb", &Obj::geti);
1883+
1884+
l.set("o", Obj(123));
1885+
EXPECT_EQ(l.eval<int>("return o.i"), 123);
1886+
EXPECT_EQ(l.eval<int>("return o:geti()"), 123);
1887+
EXPECT_EQ(l.eval<int>("return o:getb()"), 1);
1888+
}
1889+
18641890
} // namespace

0 commit comments

Comments
 (0)