summaryrefslogtreecommitdiff
path: root/thinfunc.h
blob: dcfb94a5fdd57c1bf35ab299e077271e4f9d0d16 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
/* Heap-allocation free & small memory footprint
 *   std::function alternative with limited capabilities.
 */ // single-header library

/* Copyright (c) 2026 dyknon
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the " Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom
 * the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice
 * (including the next paragraph) shall be included in all copies
 * or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#ifndef INC_THINFUNC_H
#define INC_THINFUNC_H

namespace tf{

template<class F>
struct func;
template<class R, class... Args>
struct func<R(Args...)>{
    virtual R operator()(Args...) const = 0;
};

template<class T, class F>
class anchor;
template<class T, class AT, class MT, AT AV, MT MV>
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,
        anchor<T, R(Args...)> (T::*), R (T::*)(Args...), Self, Method>;
private:
    alignas(bound_type<nullptr, nullptr>)
    char body[sizeof(bound_type<nullptr, nullptr>)];
protected:
    template<anchor<T, R(Args...)> (T::*Self), R (T::*Method)(Args...)>
    auto& bind(){
        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& 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<
    class T, class R, class... Args,
    anchor<T, R(Args...)> (T::*Self), R (T::*Method)(Args...)
>
class bound_anchor<T,
        anchor<T, R(Args...)> (T::*), R (T::*)(Args...),
        Self, Method
    >: public func<R(Args...)>{
public:
    bound_anchor(){}
    bound_anchor(const bound_anchor&) = delete;
    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) const{
        auto offset = (char *)&(((T *)0)->*Self) - (char *)0;
        T *container = (T *)((char *)this - offset);
        return (container->*Method)(args...);
    }
};

}   // namespace rf

#endif  //INC_THINFUNC_H