6#ifndef MIMICPP_FACADE_HPP
7#define MIMICPP_FACADE_HPP
18#ifndef MIMICPP_DETAIL_IS_MODULE
22 #include <type_traits>
74namespace mimicpp::facade::detail
78 inline constexpr std::size_t facadeBaseCallDepth{2u};
80 template <
typename Self>
86 ss <<
"::" << functionName;
88 return std::move(ss).str();
91 template <
typename Signature,
typename Target>
93 constexpr auto&& forward_for(Target& target)
noexcept
95 using ref = std::conditional_t<
100 return static_cast<ref
>(target);
105 inline constexpr std::size_t applyCallDepth{2u};
114 template <
typename Signature,
typename... Args>
115 constexpr decltype(
auto) apply(
auto& target, std::tuple<Args...>&& args)
117 return [&]<std::size_t... indices>([[maybe_unused]] std::index_sequence<indices...>
const) ->
decltype(
auto) {
118 return forward_for<Signature>(target)(
119 std::forward<Args>(std::get<indices>(args))...);
120 }(std::index_sequence_for<Args...>{});
126 template <
template <
typename...>
typename TargetTemplate>
131 template <
typename... Signatures>
134 template <
typename Signature,
typename... Args>
137 [[maybe_unused]]
auto*
const self,
138 std::tuple<Args...>&& args)
140 return detail::apply<Signature>(target, std::move(args));
143 template <
typename Self>
147 constexpr std::size_t skip = 1u + detail::facadeBaseCallDepth + detail::applyCallDepth;
150 .name = detail::generate_member_target_name<Self>(functionName),
151 .stacktraceSkip = skip};
157 template <
typename Self,
template <
typename...>
typename TargetTemplate>
162 template <
typename Signature,
bool isConst = Constness::as_const == signature_const_qualification_v<Signature>>
165 std::conditional_t<isConst, Self const*, Self*>>;
167 template <
typename... Signatures>
170 template <
typename Signature,
typename... Args>
171 static constexpr decltype(
auto)
invoke(
auto& target,
auto*
const self, std::tuple<Args...>&& args)
173 return detail::apply<Signature>(
175 std::tuple_cat(std::make_tuple(self), std::move(args)));
181 constexpr std::size_t skip = 1u + detail::facadeBaseCallDepth + detail::applyCallDepth;
184 .name = detail::generate_member_target_name<Self>(functionName),
185 .stacktraceSkip = skip};
189 template <
typename Self>
196 template <
typename Traits>
197 inline constexpr bool is_member_v =
false;
199 template <
typename Traits>
200 requires requires { Traits::is_member; }
201 inline constexpr bool is_member_v<Traits>{Traits::is_member};
203 template <auto specText>
204 struct apply_normalized_specs
209 bool hasConst{
false};
211 bool hasNoexcept{
false};
215 static consteval auto evaluate_specs()
217 auto const end = std::ranges::end(specText);
218 auto const find_token_begin = [&](
auto const first)
noexcept {
221 constexpr auto is_space = [](
char const c)
noexcept {
222 return ' ' == c ||
'\t' == c;
225 return std::ranges::find_if_not(first, end, is_space);
230 for (
auto tokenBegin = find_token_begin(std::ranges::begin(specText));
232 tokenBegin = find_token_begin(tokenBegin))
234 tokenBegin = (
'&' == *tokenBegin)
235 ? parse_ref_specifier(tokenBegin, end, result)
236 : parse_keyword_specifier(tokenBegin, end, result);
242 template <
typename Iter>
244 static consteval Iter parse_ref_specifier(Iter first,
auto const end, spec_info& out_info)
246 MIMICPP_ASSERT(first != end,
"First must point to the first `&` character.");
263 template <
typename Iter>
265 static consteval Iter parse_keyword_specifier(Iter first,
auto const end, spec_info& out_info)
267 MIMICPP_ASSERT(first != end,
"First must point to the first keyword character.");
269 constexpr auto is_keyword_continue = [](
char const c)
noexcept {
272 return (
'a' <= c && c <=
'z')
273 || (
'A' <= c && c <=
'Z');
277 auto const tokenEnd = std::ranges::find_if_not(first + 1u, end, is_keyword_continue);
278 std::string_view
const token{first, tokenEnd};
279 if (
constexpr std::string_view constKeyword{
"const"};
280 constKeyword == token)
282 MIMICPP_ASSERT(!out_info.hasConst,
"Const-qualifier already set.");
283 out_info.hasConst =
true;
285 else if (
constexpr std::string_view noexceptKeyword{
"noexcept"};
286 noexceptKeyword == token)
288 MIMICPP_ASSERT(!out_info.hasNoexcept,
"Noexcept-qualifier already set.");
289 out_info.hasNoexcept =
true;
291 else if (
constexpr std::string_view overrideKeyword{
"override"}, finalKeyword{
"final"};
292 overrideKeyword != token && finalKeyword != token)
294 throw "Invalid spec";
300 static constexpr auto info = evaluate_specs();
303 template <
typename Signature>
305 static consteval auto evaluate() noexcept
307 using sig_maybe_ref = std::conditional_t<
315 using sig_maybe_const = std::conditional_t<
320 using sig_maybe_noexcept = std::conditional_t<
325 return std::type_identity<sig_maybe_noexcept>{};
328 template <
typename Signature>
329 using type =
decltype(evaluate<Signature>())::type;
332 template <
typename RawSignature, auto specText>
333 using apply_normalized_specs_t = apply_normalized_specs<specText>::template type<RawSignature>;
#define MIMICPP_DETAIL_CONSTEXPR_STRING
Definition Config.hpp:60
#define MIMICPP_ASSERT(condition, msg)
Definition Config.hpp:51
#define MIMICPP_DETAIL_MODULE_EXPORT
Definition Config.hpp:19
constexpr printing::PrintTypeFn< T > print_type
Functional object, converting the given type to its textual representation.
Definition PrintType.hpp:478
typename signature_add_const_qualifier< Signature >::type signature_add_const_qualifier_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:150
typename signature_add_lvalue_ref_qualifier< Signature >::type signature_add_lvalue_ref_qualifier_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:166
typename signature_add_noexcept< Signature >::type signature_add_noexcept_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:54
typename signature_add_rvalue_ref_qualifier< Signature >::type signature_add_rvalue_ref_qualifier_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:182
typename signature_prepend_param< Signature, T >::type signature_prepend_param_t
Convenience alias, exposing the type member alias of the actual type-trait.
Definition Fwd.hpp:311
constexpr ValueCategory signature_ref_qualification_v
Convenience constant, exposing the value member of the actual type-trait.
Definition Fwd.hpp:262
basic_as_member_with_this< Self, Mock > mock_as_member_with_this
Definition Facade.hpp:190
basic_as_member< Mock > mock_as_member
Definition Facade.hpp:155
auto constexpr is_space
Definition NameLexer.hpp:28
ValueCategory
Definition Fwd.hpp:34
@ any
Definition Fwd.hpp:37
@ lvalue
Definition Fwd.hpp:35
@ rvalue
Definition Fwd.hpp:36
std::basic_ostringstream< CharT, CharTraitsT > StringStreamT
Definition Format.hpp:35
std::basic_string_view< CharT, CharTraitsT > StringViewT
Definition Fwd.hpp:392
std::basic_string< CharT, CharTraitsT > StringT
Definition Fwd.hpp:391
Definition Facade.hpp:159
static constexpr bool is_member
Definition Facade.hpp:160
static MIMICPP_DETAIL_CONSTEXPR_STRING MockSettings make_settings(auto const *const self, StringViewT const functionName)
Definition Facade.hpp:179
TargetTemplate< prepend_this< Signatures >... > target_type
Definition Facade.hpp:168
signature_prepend_param_t< Signature, std::conditional_t< isConst, Self const *, Self * > > prepend_this
Definition Facade.hpp:163
static constexpr decltype(auto) invoke(auto &target, auto *const self, std::tuple< Args... > &&args)
Definition Facade.hpp:171
Definition Facade.hpp:128
static constexpr bool is_member
Definition Facade.hpp:129
static constexpr decltype(auto) invoke(auto &target, auto *const self, std::tuple< Args... > &&args)
Definition Facade.hpp:135
TargetTemplate< Signatures... > target_type
Definition Facade.hpp:132
static MIMICPP_DETAIL_CONSTEXPR_STRING MockSettings make_settings(Self const *const self, StringViewT const functionName)
Definition Facade.hpp:145