Skip to content

Commit

Permalink
Simulate overload resolution in macros (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
mingxwa authored Jun 4, 2024
1 parent 83e766f commit ddd4ef0
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 54 deletions.
88 changes: 44 additions & 44 deletions proxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -1040,6 +1040,13 @@ using facade_builder = details::facade_builder_impl<std::tuple<>, std::tuple<>,
.relocatability = details::invalid_cl,
.destructibility = details::invalid_cl}>;

#define ___PRO_EXPAND_IMPL(__X) __X
#define ___PRO_EXPAND_MACRO_IMPL(__MACRO, __1, __2, __3, __4, __NAME, ...) \
__MACRO ## _ ## __NAME
#define ___PRO_EXPAND_MACRO(__MACRO, ...) \
___PRO_EXPAND_IMPL(___PRO_EXPAND_MACRO_IMPL( \
__MACRO, __VA_ARGS__, 4, 3, 2)(__VA_ARGS__))

#define ___PRO_DIRECT_FUNC_IMPL(...) \
noexcept(noexcept(__VA_ARGS__)) requires(requires { __VA_ARGS__; }) \
{ return __VA_ARGS__; }
Expand All @@ -1049,7 +1056,7 @@ using facade_builder = details::facade_builder_impl<std::tuple<>, std::tuple<>,
decltype(auto) operator()(::std::nullptr_t, __Args&&... __args) \
___PRO_DIRECT_FUNC_IMPL(__DEFFUNC(::std::forward<__Args>(__args)...))

#define ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, ...) \
#define ___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME, ...) \
struct __NAME { \
using __name = __NAME; \
template <class... __Args> \
Expand All @@ -1059,15 +1066,24 @@ using facade_builder = details::facade_builder_impl<std::tuple<>, std::tuple<>,
template <class __P> \
struct accessor { \
template <class... __Args> \
decltype(auto) __FUNC(__Args&&... __args) const \
decltype(auto) __FNAME(__Args&&... __args) const \
___PRO_DIRECT_FUNC_IMPL(::pro::proxy_invoke<__name>( \
static_cast<::pro::details::lazy_eval_t<const __P&, \
__Args...>>(*this), ::std::forward<__Args>(__args)...)) \
}; \
__VA_ARGS__ \
}
#define ___PRO_DEF_MEM_DISPATCH_2(__NAME, __FUNC) \
___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
#define ___PRO_DEF_MEM_DISPATCH_3(__NAME, __FUNC, __FNAME) \
___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
#define ___PRO_DEF_MEM_DISPATCH_4(__NAME, __FUNC, __FNAME, __DEFFUNC) \
___PRO_DEF_MEM_DISPATCH_IMPL( \
__NAME, __FUNC, __FNAME, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))
#define PRO_DEF_MEM_DISPATCH(__NAME, ...) \
___PRO_EXPAND_MACRO(___PRO_DEF_MEM_DISPATCH, __NAME, __VA_ARGS__)

#define ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FNAME, __FUNC, ...) \
#define ___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME, ...) \
struct __NAME { \
using __name = __NAME; \
template <class... __Args> \
Expand All @@ -1083,20 +1099,15 @@ using facade_builder = details::facade_builder_impl<std::tuple<>, std::tuple<>,
}; \
__VA_ARGS__ \
}

#define PRO_DEF_MEM_DISPATCH(__NAME, __FUNC) \
___PRO_DEF_MEM_DISPATCH_IMPL(__NAME, __FUNC)

#define PRO_DEF_MEM_DISPATCH_WITH_DEFAULT(__NAME, __FUNC, __DEFFUNC) \
___PRO_DEF_MEM_DISPATCH_IMPL( \
__NAME, __FUNC, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))

#define PRO_DEF_FREE_DISPATCH(__NAME, __FNAME, __FUNC) \
___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FNAME, __FUNC)

#define PRO_DEF_FREE_DISPATCH_WITH_DEFAULT(__NAME, __FNAME, __FUNC, __DEFFUNC) \
#define ___PRO_DEF_FREE_DISPATCH_2(__NAME, __FUNC) \
___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FUNC)
#define ___PRO_DEF_FREE_DISPATCH_3(__NAME, __FUNC, __FNAME) \
___PRO_DEF_FREE_DISPATCH_IMPL(__NAME, __FUNC, __FNAME)
#define ___PRO_DEF_FREE_DISPATCH_4(__NAME, __FUNC, __FNAME, __DEFFUNC) \
___PRO_DEF_FREE_DISPATCH_IMPL( \
__NAME, __FNAME, __FUNC, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))
__NAME, __FUNC, __FNAME, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))
#define PRO_DEF_FREE_DISPATCH(__NAME, ...) \
___PRO_EXPAND_MACRO(___PRO_DEF_FREE_DISPATCH, __NAME, __VA_ARGS__)

namespace details {

Expand Down Expand Up @@ -1354,7 +1365,7 @@ using op_dispatch_accessor = typename op_dispatch_traits<SIGN, POS>

} // namespace details

#define ___PRO_DEF_OPERATOR_DISPATCH_IMPL(__NAME, __SIGN, __POS, ...) \
#define ___PRO_DEF_OPERATOR_DISPATCH_IMPL(__NAME, __POS, __SIGN, ...) \
struct __NAME : ::pro::details::op_dispatch_base< \
__SIGN, ::pro::details::sign_pos_type::__POS> { \
using ::pro::details::op_dispatch_base< \
Expand All @@ -1364,6 +1375,18 @@ using op_dispatch_accessor = typename op_dispatch_traits<SIGN, POS>
__SIGN, ::pro::details::sign_pos_type::__POS, __NAME, __P>; \
__VA_ARGS__ \
};
#define ___PRO_DEF_OPERATOR_DISPATCH_3(__NAME, __POS, __SIGN) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL(__NAME, __POS, __SIGN)
#define ___PRO_DEF_OPERATOR_DISPATCH_4(__NAME, __POS, __SIGN, __DEFFUNC) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL( \
__NAME, __POS, __SIGN, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))
#define PRO_DEF_OPERATOR_DISPATCH(__NAME, ...) \
___PRO_EXPAND_MACRO(___PRO_DEF_OPERATOR_DISPATCH, __NAME, none, __VA_ARGS__)
#define PRO_DEF_PREFIX_OPERATOR_DISPATCH(__NAME, ...) \
___PRO_EXPAND_MACRO(___PRO_DEF_OPERATOR_DISPATCH, __NAME, left, __VA_ARGS__)
#define PRO_DEF_POSTFIX_OPERATOR_DISPATCH(__NAME, ...) \
___PRO_EXPAND_MACRO( \
___PRO_DEF_OPERATOR_DISPATCH, __NAME, right, __VA_ARGS__)

#define ___PRO_DEF_CONVERTION_DISPATCH_IMPL(__NAME, __T, ...) \
struct __NAME { \
Expand All @@ -1379,36 +1402,13 @@ using op_dispatch_accessor = typename op_dispatch_traits<SIGN, POS>
}; \
__VA_ARGS__ \
}

#define PRO_DEF_OPERATOR_DISPATCH(__NAME, __SIGN) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL(__NAME, __SIGN, none)

#define PRO_DEF_OPERATOR_DISPATCH_WITH_DEFAULT(__NAME, __SIGN, __DEFFUNC) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL( \
__NAME, __SIGN, none, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))

#define PRO_DEF_PREFIX_OPERATOR_DISPATCH(__NAME, __SIGN) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL(__NAME, __SIGN, left)

#define PRO_DEF_PREFIX_OPERATOR_DISPATCH_WITH_DEFAULT( \
__NAME, __SIGN, __DEFFUNC) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL( \
__NAME, __SIGN, left, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))

#define PRO_DEF_POSTFIX_OPERATOR_DISPATCH(__NAME, __SIGN) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL(__NAME, __SIGN, right)

#define PRO_DEF_POSTFIX_OPERATOR_DISPATCH_WITH_DEFAULT( \
__NAME, __SIGN, __DEFFUNC) \
___PRO_DEF_OPERATOR_DISPATCH_IMPL( \
__NAME, __SIGN, right, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))

#define PRO_DEF_CONVERTION_DISPATCH(__NAME, __T) \
#define ___PRO_DEF_CONVERTION_DISPATCH_2(__NAME, __T) \
___PRO_DEF_CONVERTION_DISPATCH_IMPL(__NAME, __T)

#define PRO_DEF_CONVERTION_DISPATCH_WITH_DEFAULT(__NAME, __T, __DEFFUNC) \
#define ___PRO_DEF_CONVERTION_DISPATCH_3(__NAME, __T, __DEFFUNC) \
___PRO_DEF_CONVERTION_DISPATCH_IMPL( \
__NAME, __T, ___PRO_DEFAULT_DISPATCH_CALL_IMPL(__DEFFUNC))
#define PRO_DEF_CONVERTION_DISPATCH(__NAME, ...) \
___PRO_EXPAND_MACRO(___PRO_DEF_CONVERTION_DISPATCH, __NAME, __VA_ARGS__)

} // namespace pro

Expand Down
2 changes: 1 addition & 1 deletion tests/freestanding/proxy_freestanding_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ unsigned GetDefaultHash() { return -1; }

namespace spec {

PRO_DEF_FREE_DISPATCH_WITH_DEFAULT(FreeGetHash, GetHash, ::GetHash, ::GetDefaultHash);
PRO_DEF_FREE_DISPATCH(FreeGetHash, ::GetHash, GetHash, ::GetDefaultHash);
struct Hashable : pro::facade_builder
::add_convention<FreeGetHash, unsigned()>
::build {};
Expand Down
21 changes: 13 additions & 8 deletions tests/proxy_invocation_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,15 @@ namespace spec {

PRO_DEF_OPERATOR_DISPATCH(OpCall, "()");

template <class... Os>
struct MovableCallable : pro::facade_builder
::add_convention<OpCall, Os...>
::build {};

template <class... Os>
struct Callable : pro::facade_builder
::support_copy<pro::constraint_level::nontrivial>
::add_convention<OpCall, Os...>
::add_facade<MovableCallable<Os...>>
::build {};

struct Wildcard {
Expand All @@ -32,15 +37,15 @@ struct Wildcard {

Wildcard NotImplemented(auto&&...) { throw std::runtime_error{ "Not implemented!" }; }

PRO_DEF_OPERATOR_DISPATCH_WITH_DEFAULT(WeakOpCall, "()", NotImplemented);
PRO_DEF_OPERATOR_DISPATCH(WeakOpCall, "()", NotImplemented);
template <class... Os>
struct WeakCallable : pro::facade_builder
::support_copy<pro::constraint_level::nontrivial>
::add_convention<WeakOpCall, Os...>
::build {};

PRO_DEF_FREE_DISPATCH(FreeSize, Size, std::ranges::size);
PRO_DEF_FREE_DISPATCH(FreeForEach, ForEach, std::ranges::for_each);
PRO_DEF_FREE_DISPATCH(FreeSize, std::ranges::size, Size);
PRO_DEF_FREE_DISPATCH(FreeForEach, std::ranges::for_each, ForEach);

template <class T>
struct Iterable : pro::facade_builder
Expand All @@ -57,15 +62,15 @@ pro::proxy<Container<T>> AppendImpl(C& container, T&& v) {
return &container;
}

PRO_DEF_FREE_DISPATCH(FreeAppend, Append, AppendImpl);
PRO_DEF_FREE_DISPATCH(FreeAppend, AppendImpl, Append);

template <class T>
struct Container : pro::facade_builder
::add_facade<Iterable<T>>
::template add_convention<FreeAppend, pro::proxy<Container<T>>(T)>
::build {};

PRO_DEF_MEM_DISPATCH_WITH_DEFAULT(MemAtWeak, at, NotImplemented);
PRO_DEF_MEM_DISPATCH(MemAtWeak, at, at, NotImplemented);

struct ResourceDictionary : pro::facade_builder
::add_convention<MemAtWeak, std::string(int)>
Expand All @@ -80,7 +85,7 @@ pro::proxy<F> LockImpl(const std::weak_ptr<T>& p) {
return nullptr;
}
template <class F>
PRO_DEF_FREE_DISPATCH(FreeLock, Lock, LockImpl<F>);
PRO_DEF_FREE_DISPATCH(FreeLock, LockImpl<F>, Lock);

template <class F>
struct Weak : pro::facade_builder
Expand All @@ -92,7 +97,7 @@ template <class F, class T>
auto GetWeakImpl(const std::shared_ptr<T>& p) { return pro::make_proxy<Weak<F>, std::weak_ptr<T>>(p); }

template <class F>
PRO_DEF_FREE_DISPATCH_WITH_DEFAULT(FreeGetWeak, GetWeak, GetWeakImpl<F>, std::nullptr_t);
PRO_DEF_FREE_DISPATCH(FreeGetWeak, GetWeakImpl<F>, GetWeak, std::nullptr_t);

struct SharedStringable : pro::facade_builder
::add_facade<utils::spec::Stringable>
Expand Down
2 changes: 1 addition & 1 deletion tests/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ class LifetimeTracker {
namespace spec {

using std::to_string;
PRO_DEF_FREE_DISPATCH(FreeToString, ToString, to_string);
PRO_DEF_FREE_DISPATCH(FreeToString, to_string, ToString);

struct Stringable : pro::facade_builder
::add_convention<FreeToString, std::string()>
Expand Down

0 comments on commit ddd4ef0

Please sign in to comment.