diff options
| author | dyknon dyknonr5fjp | 2026-09-10 00:52:11 +0900 |
|---|---|---|
| committer | dyknon dyknonr5fjp | 2026-09-10 00:52:11 +0900 |
| commit | 92f256160f316c1d48fa12c56e6f2608b2b33811 (patch) | |
| tree | 154ca70a2a9da61f77810dd75a2aad33683aea8c | |
| parent | d98e139d08d2d24426d75384f8789ccc7279bca4 (diff) | |
| -rw-r--r-- | thinfunc-example.cc | 22 | ||||
| -rw-r--r-- | thinfunc.h | 26 |
2 files changed, 28 insertions, 20 deletions
diff --git a/thinfunc-example.cc b/thinfunc-example.cc index 1cf12d6..10446bf 100644 --- a/thinfunc-example.cc +++ b/thinfunc-example.cc @@ -33,20 +33,15 @@ using namespace tf; struct test{ std::string name; - test(std::string name): name(name){} + test(std::string name): name(name){ + m1.bind<&test::m1, &test::message1>(); + m2.bind<&test::m2, &test::message2>(); + t.bind<&test::t, &test::time>(); + } anchor<test, void()> m1; - func<void()>& get_m1(){ - return m1.bind<&test::m1, &test::message1>(); - } anchor<test, void(std::string)> m2; - func<void(std::string)>& get_m2(){ - return m2.bind<&test::m2, &test::message2>(); - } anchor<test, std::string()> t; - func<std::string()>& get_t(){ - return t.bind<&test::t, &test::time>(); - } void message1(){ std::println("hello! I'm {}.", name); @@ -74,10 +69,9 @@ struct test{ int main(){ test o("a test object"); - func<void()>& m1 = o.get_m1(); - func<void(std::string)>& m2 = o.get_m2(); - o.get_t(); - func<std::string()>& t = o.t.assume_bound<&test::t, &test::time>(); + func<void()>& m1 = o.m1.bound(); + func<void(std::string)>& m2 = o.m2.bound(); + func<std::string()>& t = o.t.bound<&test::t, &test::time>(); m1(); m2(t()); @@ -33,7 +33,7 @@ template<class F> struct func; template<class R, class... Args> struct func<R(Args...)>{ - virtual R operator()(Args...) = 0; + virtual R operator()(Args...) const = 0; }; template<class T, class F> @@ -43,6 +43,7 @@ class bound_anchor; template<class T, class R, class... Args> class anchor<T, R(Args...)>{ + friend T; public: template<anchor<T, R(Args...)> (T::*Self), R (T::*Method)(Args...)> using bound_type = bound_anchor<T, @@ -50,15 +51,28 @@ public: private: alignas(bound_type<nullptr, nullptr>) char body[sizeof(bound_type<nullptr, nullptr>)]; -public: +protected: template<anchor<T, R(Args...)> (T::*Self), R (T::*Method)(Args...)> auto& bind(){ - return *(new (this->body) bound_type<Self, Method>()); + static_assert(sizeof(bound_type<Self, Method>) == sizeof(body)); + static_assert( + (func<R(Args...)> *)(bound_type<nullptr, nullptr> *)nullptr + == (func<R(Args...)> *)(bound_type<Self, Method> *)nullptr); + return *(new (body) bound_type<Self, Method>()); } +public: template<anchor<T, R(Args...)> (T::*Self), R (T::*Method)(Args...)> - auto& assume_bound() const{ - return *(bound_type<Self, Method> *)this->body; + auto& bound(){ + return *(bound_type<Self, Method> *)body; + } + func<R(Args...)>& bound(){ + return *(func<R(Args...)> *)(bound_type<nullptr, nullptr> *)body; } + anchor(const anchor&) = delete; + anchor(const anchor&&) = delete; + anchor& operator=(const anchor&) = delete; + anchor& operator=(const anchor&&) = delete; + anchor() = default; }; template< @@ -75,7 +89,7 @@ public: bound_anchor(const bound_anchor&&) = delete; bound_anchor& operator=(const bound_anchor&) = delete; bound_anchor& operator=(const bound_anchor&&) = delete; - virtual R operator()(Args... args){ + virtual R operator()(Args... args) const{ auto offset = (char *)&(((T *)0)->*Self) - (char *)0; T *container = (T *)((char *)this - offset); return (container->*Method)(args...); |
