Any++
Loading...
Searching...
No Matches
anyxx_function.hpp
1#pragma once
2
4
5namespace anyxx {
6
7struct constness {};
8struct const_ : constness {
9 using type = const_void;
10};
11struct mutable_ : constness {
12 using type = mutable_void;
13};
14
15template <typename Constness, typename R, typename... Args>
16struct function_v_table : any_v_table {
17 R (*f_)(typename Constness::type, Args...);
18 template <typename Concrete>
19 function_v_table([[maybe_unused]] std::in_place_type_t<Concrete> concrete)
20 : any_v_table(concrete) {
21 f_ = +[](typename Constness::type self_ptr, Args... args) -> R {
22 return std::invoke(*unchecked_unerase_cast<Concrete>(self_ptr),
23 std::forward<Args>(args)...);
24 };
25 }
26};
27
28template <typename Constness, typename R, typename... Args>
29struct function;
30template <typename Constness, typename R, typename... Args>
31struct function<R(Args...), Constness> : base_trait {
32 using v_table_t = function_v_table<Constness, R, Args...>;
33 template <typename Self>
34 auto operator()(this Self &&self, Args... args) -> R
35 requires(const_correct_call_for_proxy_and_self<
36 typename Constness::type, typename std::decay_t<Self>::proxy_t,
37 std::is_const_v<std::remove_reference_t<Self>>,
38 false /*exact const*/>)
39 {
40 using self_t = std::decay_t<Self>;
41 if constexpr (self_t::dyn) {
42 return get_v_table(self)->f_(get_proxy_ptr(self),
43 std::forward<Args>(args)...);
44 } else {
45 using T =
46 typename proxy_trait<typename self_t::proxy_t>::static_dispatch_t;
47 return std::invoke(get_proxy_value(std::forward<Self>(self)),
48 std::forward<Args>(args)...);
49 }
50 }
51};
52
53namespace self_test {
54struct functor {
55 int operator()(double) const;
56};
57using f_const_const = any<cref, function<int(double), const_>>;
58static_assert(std::invocable<f_const_const, double>);
59using f_const_mutable = any<cref, function<int(double), mutable_>>;
60static_assert(!std::invocable<f_const_mutable, double>);
61using f_mutable_const = any<mutref, function<int(double), const_>>;
62static_assert(std::invocable<f_mutable_const, double>);
63using f_mutable_mutable = any<mutref, function<int(double), mutable_>>;
64static_assert(std::invocable<f_mutable_mutable, double>);
65
66using f_const_const_val =
67 any<using_<functor const &>, function<int(double), const_>>;
68static_assert(std::invocable<f_const_const_val, double>);
69using f_const_mutable_val =
70 any<using_<functor const &>, function<int(double), mutable_>>;
71static_assert(!std::invocable<f_const_mutable_val, double>);
72using f_mutable_const_val =
73 any<using_<functor &>, function<int(double), const_>>;
74static_assert(std::invocable<f_mutable_const_val, double>);
75using f_mutable_mutable_val =
76 any<using_<functor &>, function<int(double), mutable_>>;
77static_assert(std::invocable<f_mutable_mutable_val, double>);
78} // namespace self_test
79
80} // namespace anyxx
C++ header only library for external polymorphism.
observer< const_void > cref
Definition anyxx.hpp:1863
observer< mutable_void > mutref
Definition anyxx.hpp:1867
Basic lifetime functionality.
Definition anyxx.hpp:1368
any_v_table(std::in_place_type_t< Concrete > concrete)
Type-erasing constructor.
Definition anyxx.hpp:1374