summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordyknon dyknonr5fjp2026-09-10 00:52:11 +0900
committerdyknon dyknonr5fjp2026-09-10 00:52:11 +0900
commit92f256160f316c1d48fa12c56e6f2608b2b33811 (patch)
tree154ca70a2a9da61f77810dd75a2aad33683aea8c
parentd98e139d08d2d24426d75384f8789ccc7279bca4 (diff)
better syntax, more protection, std::function compatibilityHEADmaster
-rw-r--r--thinfunc-example.cc22
-rw-r--r--thinfunc.h26
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());
diff --git a/thinfunc.h b/thinfunc.h
index c75c33a..dcfb94a 100644
--- a/thinfunc.h
+++ b/thinfunc.h
@@ -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...);