Skip to content

Commit

Permalink
support 'noexcept'
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Sep 14, 2024
1 parent 0840ff2 commit 91a6496
Show file tree
Hide file tree
Showing 3 changed files with 192 additions and 177 deletions.
186 changes: 109 additions & 77 deletions include/yorel/yomm2/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,13 +143,13 @@ using remove_virtual = typename remove_virtual_<T>::type;
template<typename>
struct parameter_type_list;

template<typename ReturnType, typename... ParameterTypes>
struct parameter_type_list<ReturnType(ParameterTypes...)> {
template<typename Return, typename... ParameterTypes>
struct parameter_type_list<Return(ParameterTypes...)> {
using type = types<ParameterTypes...>;
};

template<typename ReturnType, typename... ParameterTypes>
struct parameter_type_list<ReturnType (*)(ParameterTypes...)> {
template<typename Return, typename... ParameterTypes>
struct parameter_type_list<Return (*)(ParameterTypes...)> {
using type = types<ParameterTypes...>;
};

Expand Down Expand Up @@ -526,6 +526,13 @@ inline auto final_virtual_ptr(Class& obj) {
// =============================================================================
// Method

template<bool Value>
struct noexcept_if {
static constexpr bool value = Value;
};

using noexcept_ = noexcept_if<true>;

namespace detail {

template<class Policy, typename P, typename Q>
Expand Down Expand Up @@ -618,18 +625,18 @@ constexpr bool has_next_v = std::is_same_v<type_next_t<Container>, Next>;

template<typename Method, typename Container>
struct next_aux {
static typename Method::next_type next;
static typename Method::Next next;
};

template<typename Method, typename Container>
typename Method::next_type next_aux<Method, Container>::next;
typename Method::Next next_aux<Method, Container>::next;

template<auto F, typename T>
struct member_function_thunk;

template<auto F, class ReturnType, class C, typename... Args>
struct member_function_thunk<F, ReturnType (C::*)(Args...)> {
static auto fn(C* this_, Args&&... args) -> ReturnType {
template<auto F, class Return, class C, typename... Args>
struct member_function_thunk<F, Return (C::*)(Args...)> {
static auto fn(C* this_, Args&&... args) -> Return {
return (this_->*F)(args...);
}
};
Expand All @@ -645,25 +652,39 @@ struct has_static_offsets<
Method, std::void_t<decltype(static_offsets<Method>::slots)>>
: std::true_type {};

template<class Class>
struct is_noexcept : std::false_type {};

template<bool Value>
struct is_noexcept<noexcept_if<Value>> : std::true_type {};

} // namespace detail

template<typename Name, typename Signature, class Policy = YOMM2_DEFAULT_POLICY>
template<typename Name, typename Signature, class... More>
struct method;

template<typename Name, typename ReturnType, class Policy, typename... Args>
struct method<Name, ReturnType(Args...), Policy> : detail::method_info {
using self_type = method;
using policy_type = Policy;
using declared_argument_types = detail::types<Args...>;
using call_argument_types = boost::mp11::mp_transform<
detail::remove_virtual, declared_argument_types>;
using virtual_argument_types =
typename detail::polymorphic_types<declared_argument_types>;
using signature_type = ReturnType(Args...);
using return_type = ReturnType;
using function_pointer_type =
ReturnType (*)(detail::remove_virtual<Args>...);
using next_type = function_pointer_type;
template<typename Name, typename Return, typename... Args, class... Options>
struct method<Name, Return(Args...), Options...> : detail::method_info {
// Convention: everything extracted from template arguments is capitalized
// like the arguments themselves.
using Policy = detail::get_policy<Options...>;
static constexpr bool NoExcept = boost::mp11::mp_at<
detail::types<Options..., noexcept_if<false>>,
boost::mp11::mp_find_if<
detail::types<Options..., noexcept_if<false>>,
detail::is_noexcept>>::value;
using DeclaredParameters = detail::types<Args...>;
using CallParameters =
boost::mp11::mp_transform<detail::remove_virtual, DeclaredParameters>;
using VirtualParameters =
typename detail::polymorphic_types<DeclaredParameters>;
using Signature = Return(Args...);
using FunctionPointer = Return (*)(detail::remove_virtual<Args>...);
using Next = FunctionPointer;

// These are publicly available aliases.
using return_type = Return;
using next_type = Next;

static constexpr auto arity = detail::arity<Args...>;
static_assert(arity > 0, "method must have at least one virtual argument");
Expand All @@ -690,7 +711,8 @@ struct method<Name, ReturnType(Args...), Policy> : detail::method_info {
auto vptr(const ArgType& arg) const -> const std::uintptr_t*;

template<class Error>
void check_static_offset(std::size_t actual, std::size_t expected) const;
void check_static_offset(std::size_t actual, std::size_t expected) const
noexcept(NoExcept);

template<typename MethodArgList, typename ArgType, typename... MoreArgTypes>
auto resolve_uni(const ArgType& arg, const MoreArgTypes&... more_args) const
Expand All @@ -711,22 +733,21 @@ struct method<Name, ReturnType(Args...), Policy> : detail::method_info {
const MoreArgTypes&... more_args) const -> std::uintptr_t;

template<typename... ArgType>
function_pointer_type resolve(const ArgType&... args) const;
FunctionPointer resolve(const ArgType&... args) const;

auto operator()(detail::remove_virtual<Args>... args) const -> return_type;
auto operator()(detail::remove_virtual<Args>... args) const -> Return;

static BOOST_NORETURN auto
not_implemented_handler(detail::remove_virtual<Args>... args)
-> return_type;
not_implemented_handler(detail::remove_virtual<Args>... args) -> Return;
static BOOST_NORETURN auto
ambiguous_handler(detail::remove_virtual<Args>... args) -> return_type;
ambiguous_handler(detail::remove_virtual<Args>... args) -> Return;

template<typename Container>
using next = detail::next_aux<method, Container>;

template<auto Function>
struct add_function {
explicit add_function(next_type* next = nullptr) {
explicit add_function(Next* next = nullptr) {

static detail::definition_info info;

Expand All @@ -740,12 +761,12 @@ struct method<Name, ReturnType(Args...), Policy> : detail::method_info {
info.next = reinterpret_cast<void**>(next);
using parameter_types =
typename detail::parameter_type_list<decltype(Function)>::type;
info.pf = (void*)detail::thunk<
Policy, signature_type, Function, parameter_types>::fn;
info.pf = (void*)
detail::thunk<Policy, Signature, Function, parameter_types>::fn;
using spec_type_ids = detail::type_id_list<
Policy,
detail::spec_polymorphic_types<
Policy, declared_argument_types, parameter_types>>;
Policy, DeclaredParameters, parameter_types>>;
info.vp_begin = spec_type_ids::begin;
info.vp_end = spec_type_ids::end;
fn.specs.push_back(info);
Expand All @@ -770,7 +791,7 @@ struct method<Name, ReturnType(Args...), Policy> : detail::method_info {

template<typename Container>
struct add_definition
: add_definition_<Container, detail::has_next_v<Container, next_type>> {
: add_definition_<Container, detail::has_next_v<Container, Next>> {
using type = add_definition; // make it a meta-function
};

Expand All @@ -785,24 +806,24 @@ struct method<Name, ReturnType(Args...), Policy> : detail::method_info {

template<typename Container>
struct use_next {
static next_type next;
static Next next;
};
};

template<typename Name, typename ReturnType, class Policy, typename... Args>
method<Name, ReturnType(Args...), Policy>
method<Name, ReturnType(Args...), Policy>::fn;
template<typename Name, typename Return, typename... Args, class... Options>
method<Name, Return(Args...), Options...>
method<Name, Return(Args...), Options...>::fn;

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
template<typename Container>
typename method<Name, ReturnType(Args...), Policy>::next_type
method<Name, ReturnType(Args...), Policy>::use_next<Container>::next;
typename method<Name, Return(Args...), Options...>::Next
method<Name, Return(Args...), Options...>::use_next<Container>::next;

template<typename T>
constexpr bool is_method = std::is_base_of_v<detail::method_info, T>;

template<typename Name, typename ReturnType, class Policy, typename... Args>
method<Name, ReturnType(Args...), Policy>::method() {
template<typename Name, typename Return, typename... Args, class... Options>
method<Name, Return(Args...), Options...>::method() {
this->slots_strides_ptr = slots_strides;

#ifndef BOOST_NO_RTTI
Expand All @@ -815,7 +836,7 @@ method<Name, ReturnType(Args...), Policy>::method() {
Policy,
boost::mp11::mp_transform_q<
boost::mp11::mp_bind_front<detail::polymorphic_type, Policy>,
virtual_argument_types>>;
VirtualParameters>>;
this->vp_begin = virtual_type_ids::begin;
this->vp_end = virtual_type_ids::end;
this->not_implemented = (void*)not_implemented_handler;
Expand All @@ -824,28 +845,28 @@ method<Name, ReturnType(Args...), Policy>::method() {
Policy::methods.push_back(*this);
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
std::size_t
method<Name, ReturnType(Args...), Policy>::slots_strides[2 * arity - 1];
method<Name, Return(Args...), Options...>::slots_strides[2 * arity - 1];

template<typename Name, typename ReturnType, class Policy, typename... Args>
method<Name, ReturnType(Args...), Policy>::~method() {
template<typename Name, typename Return, typename... Args, class... Options>
method<Name, Return(Args...), Options...>::~method() {
Policy::methods.remove(*this);
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
auto inline method<Name, ReturnType(Args...), Policy>::operator()(
detail::remove_virtual<Args>... args) const ->
typename method<Name, ReturnType(Args...), Policy>::return_type {
template<typename Name, typename Return, typename... Args, class... Options>
auto inline method<Name, Return(Args...), Options...>::operator()(
detail::remove_virtual<Args>... args) const -> Return {
using namespace detail;
auto pf = resolve(argument_traits<Policy, Args>::rarg(args)...);

return pf(std::forward<remove_virtual<Args>>(args)...);
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
template<typename... ArgType>
inline typename method<Name, ReturnType(Args...), Policy>::function_pointer_type
method<Name, ReturnType(Args...), Policy>::resolve(
inline typename method<Name, Return(Args...), Options...>::FunctionPointer
method<Name, Return(Args...), Options...>::resolve(
const ArgType&... args) const {
using namespace detail;

Expand All @@ -857,13 +878,13 @@ method<Name, ReturnType(Args...), Policy>::resolve(
pf = resolve_multi_first<0, types<Args...>, ArgType...>(args...);
}

return reinterpret_cast<function_pointer_type>(pf);
return reinterpret_cast<FunctionPointer>(pf);
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
template<typename ArgType>
inline auto
method<Name, ReturnType(Args...), Policy>::vptr(const ArgType& arg) const
method<Name, Return(Args...), Options...>::vptr(const ArgType& arg) const
-> const std::uintptr_t* {
if constexpr (is_virtual_ptr<ArgType>) {
return arg._vptr();
Expand All @@ -874,10 +895,10 @@ method<Name, ReturnType(Args...), Policy>::vptr(const ArgType& arg) const
}
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
template<class Error>
inline void method<Name, ReturnType(Args...), Policy>::check_static_offset(
std::size_t actual, std::size_t expected) const {
inline void method<Name, Return(Args...), Options...>::check_static_offset(
std::size_t actual, std::size_t expected) const noexcept(NoExcept) {
using namespace detail;

if (actual != expected) {
Expand All @@ -893,9 +914,9 @@ inline void method<Name, ReturnType(Args...), Policy>::check_static_offset(
}
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
template<typename MethodArgList, typename ArgType, typename... MoreArgTypes>
inline auto method<Name, ReturnType(Args...), Policy>::resolve_uni(
inline auto method<Name, Return(Args...), Options...>::resolve_uni(
const ArgType& arg, const MoreArgTypes&... more_args) const
-> std::uintptr_t {

Expand Down Expand Up @@ -926,11 +947,11 @@ inline auto method<Name, ReturnType(Args...), Policy>::resolve_uni(
}
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
template<
std::size_t VirtualArg, typename MethodArgList, typename ArgType,
typename... MoreArgTypes>
inline auto method<Name, ReturnType(Args...), Policy>::resolve_multi_first(
inline auto method<Name, Return(Args...), Options...>::resolve_multi_first(
const ArgType& arg, const MoreArgTypes&... more_args) const
-> std::uintptr_t {

Expand Down Expand Up @@ -972,11 +993,11 @@ inline auto method<Name, ReturnType(Args...), Policy>::resolve_multi_first(
}
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
template<
std::size_t VirtualArg, typename MethodArgList, typename ArgType,
typename... MoreArgTypes>
inline auto method<Name, ReturnType(Args...), Policy>::resolve_multi_next(
inline auto method<Name, Return(Args...), Options...>::resolve_multi_next(
const std::uintptr_t* dispatch, const ArgType& arg,
const MoreArgTypes&... more_args) const -> std::uintptr_t {

Expand Down Expand Up @@ -1021,12 +1042,10 @@ inline auto method<Name, ReturnType(Args...), Policy>::resolve_multi_next(
}
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
BOOST_NORETURN auto
method<Name, ReturnType(Args...), Policy>::not_implemented_handler(
detail::remove_virtual<Args>... args) ->
typename method<Name, ReturnType(Args...), Policy>::return_type {

method<Name, Return(Args...), Options...>::not_implemented_handler(
detail::remove_virtual<Args>... args) -> Return {
if constexpr (Policy::template has_facet<policies::error_handler>) {
resolution_error error;
error.status = resolution_error::no_definition;
Expand All @@ -1044,11 +1063,10 @@ method<Name, ReturnType(Args...), Policy>::not_implemented_handler(
abort(); // in case user handler "forgets" to abort
}

template<typename Name, typename ReturnType, class Policy, typename... Args>
template<typename Name, typename Return, typename... Args, class... Options>
BOOST_NORETURN auto
method<Name, ReturnType(Args...), Policy>::ambiguous_handler(
detail::remove_virtual<Args>... args) ->
typename method<Name, ReturnType(Args...), Policy>::return_type {
method<Name, Return(Args...), Options...>::ambiguous_handler(
detail::remove_virtual<Args>... args) -> Return {
if constexpr (Policy::template has_facet<policies::error_handler>) {
resolution_error error;
error.status = resolution_error::ambiguous;
Expand All @@ -1066,6 +1084,20 @@ method<Name, ReturnType(Args...), Policy>::ambiguous_handler(
abort(); // in case user handler "forgets" to abort
}

namespace detail {

// See 'declare_method'.

template<typename...>
struct method_macro_aux;

template<typename Name, typename Signature, class... Options>
struct method_macro<Name, Signature, types<Options...>> {
using type = method<Name, Signature, Options...>;
};

} // namespace detail

#ifndef BOOST_NO_RTTI

inline auto set_error_handler(error_handler_type handler)
Expand Down
Loading

0 comments on commit 91a6496

Please sign in to comment.