mimic++ v5
Loading...
Searching...
No Matches
CallConvention.hpp
Go to the documentation of this file.
1// // Copyright Dominic (DNKpp) Koepke 2024 - 2024.
2// // Distributed under the Boost Software License, Version 1.0.
3// // (See accompanying file LICENSE_1_0.txt or copy at
4// // https://www.boost.org/LICENSE_1_0.txt)
5
6#ifndef MIMICPP_CALL_CONVENTION_HPP
7#define MIMICPP_CALL_CONVENTION_HPP
8
9#include "mimic++/Fwd.hpp"
11
12#include <concepts>
13#include <source_location>
14#include <tuple>
15
16namespace mimicpp
17{
52}
53
61#define MIMICPP_DETAIL_DEFINE_REMOVE_CALL_CONVENTION(call_convention, specs) \
62 template <typename Return, typename... Params> \
63 struct remove_call_convention<Return call_convention(Params...) specs> \
64 { \
65 using type = Return(Params...) specs; \
66 }
67
75#define MIMICPP_DETAIL_DEFINE_ADD_CALL_CONVENTION(call_convention, specs) \
76 template <typename Return, typename... Params> \
77 struct add_call_convention<Return(Params...) specs> \
78 { \
79 using type = Return call_convention(Params...) specs; \
80 }
81
88#define MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_CALL_INTERFACE(call_convention, specs) \
89 template <typename Derived, typename Return, typename... Params> \
90 class CallInterface< \
91 Derived, \
92 Return call_convention(Params...) specs> \
93 { \
94 public: \
95 constexpr Return call_convention operator()( \
96 Params... params, \
97 const ::std::source_location& from = ::std::source_location::current()) specs \
98 { \
99 return static_cast<const Derived&>(*this) \
100 .handle_call(::std::tuple{::std::ref(params)...}, from); \
101 } \
102 }
103
110#define MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, specs) \
111 MIMICPP_DETAIL_DEFINE_REMOVE_CALL_CONVENTION(call_convention, specs); \
112 MIMICPP_DETAIL_DEFINE_ADD_CALL_CONVENTION(call_convention, specs); \
113 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_CALL_INTERFACE(call_convention, specs)
114
123#define MIMICPP_REGISTER_CALL_CONVENTION(call_convention, namespace_name) \
124 namespace namespace_name \
125 { \
126 struct tag \
127 { \
128 }; \
129 \
130 inline constexpr bool is_default_call_convention = ::std::same_as<void(), void call_convention()>; \
131 \
132 template <typename Signature> \
133 struct remove_call_convention; \
134 \
135 template <typename Signature> \
136 using remove_call_convention_t = typename remove_call_convention<Signature>::type; \
137 \
138 template <typename Signature> \
139 concept has_call_convention = !std::same_as<Signature, remove_call_convention_t<Signature>>; \
140 \
141 template <typename Signature> \
142 struct add_call_convention; \
143 \
144 template <typename Signature> \
145 using add_call_convention_t = typename add_call_convention<Signature>::type; \
146 \
147 template <has_call_convention Signature> \
148 struct add_call_convention<Signature> \
149 { \
150 using type = Signature; \
151 }; \
152 \
153 template <typename Derived, typename Signature> \
154 class CallInterface; \
155 \
156 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, ); \
157 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, noexcept); \
158 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, const); \
159 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, const noexcept); \
160 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, &); \
161 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, & noexcept); \
162 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, const&); \
163 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, const& noexcept); \
164 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, &&); \
165 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, && noexcept); \
166 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, const&&); \
167 MIMICPP_DETAIL_DEFINE_CALL_CONVENTION_SPECIALIZATIONS(call_convention, const&& noexcept); \
168 } \
169 \
170 template <::namespace_name::has_call_convention Signature> \
171 requires(!::namespace_name::is_default_call_convention) \
172 struct mimicpp::signature_call_convention<Signature> \
173 { \
174 using type = ::namespace_name::tag; \
175 }; \
176 \
177 /* In cases, where the call-convention is the default, we still want to get this tag, \
178 because it's not guaranteed, that it will be applied on member functions (e.g. __vectorcall). \
179 Due to this, we must explicitly mark the call-interface operators.*/ \
180 template <::mimicpp::has_default_call_convention Signature> \
181 requires ::namespace_name::is_default_call_convention \
182 struct mimicpp::signature_call_convention<Signature> \
183 { \
184 using type = ::namespace_name::tag; \
185 }; \
186 \
187 template <> \
188 struct mimicpp::call_convention_traits<::namespace_name::tag> \
189 { \
190 using tag_t = ::namespace_name::tag; \
191 \
192 template <typename Signature> \
193 using remove_call_convention_t = ::namespace_name::remove_call_convention_t<Signature>; \
194 \
195 template <typename Signature> \
196 using add_call_convention_t = ::namespace_name::add_call_convention_t<Signature>; \
197 \
198 template <typename Derived, typename Signature> \
199 using call_interface_t = ::namespace_name::CallInterface<Derived, Signature>; \
200 }
201
202#endif
Definition BoostTest.hpp:20