@@ -23,10 +23,10 @@ inline constexpr FunctionVTable<Res, Args...> unset_vtable{
2323 .destroy = [](void *) {},
2424};
2525
26- template <typename Target, typename Res, typename ... Args>
26+ template <bool Copyable, typename Target, typename Res, typename ... Args>
2727inline constexpr FunctionVTable<Res, Args...> vtable_for{
2828 .call = [](void * target, Args... args) -> Res { return (*reinterpret_cast <Target*>(target))(std::forward<Args>(args)...); },
29- .clone = [](void * target) -> void * { return new Target (*reinterpret_cast <Target*>(target)); },
29+ .clone = [](void * target) -> void * { if constexpr (Copyable) { return new Target (*reinterpret_cast <Target*>(target)); } return nullptr ; },
3030 .destroy = [](void * target) { delete reinterpret_cast <Target*>(target); }
3131};
3232
@@ -37,18 +37,18 @@ inline constexpr FunctionVTable<Res, Args...> vtable_for_func{
3737 .destroy = [](void * target) {}
3838};
3939
40- template <typename F>
41- class Function ;
40+ template <bool Copyable, typename F>
41+ class FunctionImpl ;
4242
43- template <typename Res, typename ... Args>
44- class Function < Res (Args...)>
43+ template <bool Copyable, typename Res, typename ... Args>
44+ class FunctionImpl <Copyable, Res (Args...)>
4545{
4646public:
47- Function () = default ;
47+ FunctionImpl () = default ;
4848
4949 template <typename Target>
50- requires (not std::is_same_v<Function , std::remove_cvref_t <Target>>)
51- Function (Target&& target)
50+ requires (not std::is_same_v<FunctionImpl , std::remove_cvref_t <Target>>)
51+ FunctionImpl (Target&& target)
5252 {
5353 using EffectiveTarget = std::remove_cvref_t <Target>;
5454 if constexpr (std::is_convertible_v<EffectiveTarget, Res (*)(Args...)>)
@@ -59,33 +59,34 @@ public:
5959 else
6060 {
6161 m_target = new EffectiveTarget (std::forward<Target>(target));
62- m_vtable = &vtable_for<EffectiveTarget, Res, Args...>;
62+ m_vtable = &vtable_for<Copyable, EffectiveTarget, Res, Args...>;
6363 }
6464 }
6565
66- Function (const Function& other) : m_target(other.m_vtable->clone (other.m_target)), m_vtable(other.m_vtable)
66+ FunctionImpl (const FunctionImpl& other) requires Copyable
67+ : m_target(other.m_vtable->clone (other.m_target)), m_vtable(other.m_vtable)
6768 {
6869 }
6970
70- Function (Function && other) : m_target(other.m_target), m_vtable(other.m_vtable)
71+ FunctionImpl (FunctionImpl && other) : m_target(other.m_target), m_vtable(other.m_vtable)
7172 {
7273 other.m_target = nullptr ;
7374 other.m_vtable = &unset_vtable<Res, Args...>;
7475 }
7576
76- ~Function ()
77+ ~FunctionImpl ()
7778 {
7879 m_vtable->destroy (m_target);
7980 }
8081
81- Function & operator =(const Function & other)
82+ FunctionImpl & operator =(const FunctionImpl & other) requires Copyable
8283 {
8384 m_target = other.m_vtable ->clone (other.m_target );
8485 m_vtable = other.m_vtable ;
8586 return *this ;
8687 }
8788
88- Function & operator =(Function && other)
89+ FunctionImpl & operator =(FunctionImpl && other)
8990 {
9091 m_target = other.m_target ;
9192 m_vtable = other.m_vtable ;
@@ -106,6 +107,12 @@ private:
106107 const FunctionVTable<Res, Args...>* m_vtable = &unset_vtable<Res, Args...>;
107108};
108109
110+ template <typename F>
111+ using Function = FunctionImpl<true , F>;
112+
113+ template <typename F>
114+ using MoveOnlyFunction = FunctionImpl<false , F>;
115+
109116}
110117
111118#endif // function_hh_INCLUDED
0 commit comments