Skip to content

Commit

Permalink
N2216 ambiguity resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
jll63 committed Oct 5, 2024
1 parent 12ca69e commit 152d311
Show file tree
Hide file tree
Showing 11 changed files with 478 additions and 269 deletions.
2 changes: 1 addition & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,5 @@ if (NOT (MSVC AND YOMM2_SHARED))
# would need to add the path to the directory containing yomm2.dll to PATH.
# Anyway, if it works with static linking, it is very unlikely that it fails
# with the runtime in a DLL.
add_subdirectory(generator)
# add_subdirectory(generator)
endif()
93 changes: 44 additions & 49 deletions include/yorel/yomm2/core.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,9 @@ auto optimal_cast(B&& obj) -> decltype(auto) {
// virtual_traits

template<class Policy, typename T>
struct virtual_traits;
struct virtual_traits {
using polymorphic_type = void;
};

template<class Policy, typename T>
struct virtual_traits<Policy, T&> {
Expand All @@ -178,6 +180,20 @@ struct virtual_traits<Policy, T&> {
}
};

template<class Policy, typename T>
struct virtual_traits<Policy, T*> {
using polymorphic_type = std::remove_cv_t<T>;

static auto rarg(const T* arg) -> const T& {
return *arg;
}

template<typename D>
static auto cast(T* obj) -> D* {
return &detail::optimal_cast<Policy, D&>(*obj);
}
};

template<class Policy, typename T>
struct virtual_traits<Policy, T&&> {
using polymorphic_type = std::remove_cv_t<T>;
Expand Down Expand Up @@ -224,7 +240,7 @@ using polymorphic_types = boost::mp11::mp_transform<
remove_virtual, boost::mp11::mp_filter<detail::is_virtual, MethodArgList>>;

template<class Policy, typename T>
struct argument_traits {
struct parameter_traits {
static auto rarg(const T& arg) -> const T& {
return arg;
}
Expand All @@ -236,14 +252,14 @@ struct argument_traits {
};

template<class Policy, typename T>
struct argument_traits<Policy, virtual_<T>> : virtual_traits<Policy, T> {};
struct parameter_traits<Policy, virtual_<T>> : virtual_traits<Policy, T> {};

template<class Policy, class Class>
struct argument_traits<Policy, virtual_ptr<Class, Policy>>
struct parameter_traits<Policy, virtual_ptr<Class, Policy>>
: virtual_traits<Policy, virtual_ptr<Class, Policy>> {};

template<class Policy, class Class>
struct argument_traits<Policy, const virtual_ptr<Class, Policy>&>
struct parameter_traits<Policy, const virtual_ptr<Class, Policy>&>
: virtual_traits<Policy, const virtual_ptr<Class, Policy>&> {};

} // namespace detail
Expand Down Expand Up @@ -463,7 +479,8 @@ class virtual_ptr {
virtual_ptr_traits<Class, Policy>::template cast<Other>(obj);
} else {
result.obj =
&detail::optimal_cast<Policy, typename Other::element_type&>(*obj);
&detail::optimal_cast<Policy, typename Other::element_type&>(
*obj);
}

return result;
Expand Down Expand Up @@ -607,8 +624,6 @@ class method<Name(Parameters...), Return, Policy> : public detail::method_info {
static BOOST_NORETURN auto
not_implemented_handler(detail::remove_virtual<Parameters>... args)
-> Return;
static BOOST_NORETURN auto
ambiguous_handler(detail::remove_virtual<Parameters>... args) -> Return;

template<auto, typename>
struct thunk;
Expand Down Expand Up @@ -646,7 +661,7 @@ class method<Name(Parameters...), Return, Policy> : public detail::method_info {
detail::types<OverriderParameters...>>>;
};

template<auto Function>
template<auto Function, typename FnReturnType>
struct override_impl {
explicit override_impl(FunctionPointer* next = nullptr);
};
Expand All @@ -656,19 +671,17 @@ class method<Name(Parameters...), Return, Policy> : public detail::method_info {

template<auto Function, typename FnReturnType, typename... FnParameters>
struct override_aux<Function, FnReturnType (*)(FnParameters...)>
: override_impl<Function> {
};
: override_impl<Function, FnReturnType> {};

template<
auto Function, class FnClass, typename FnReturnType,
typename... FnParameters>
struct override_aux<
Function, FnReturnType (FnClass::*)(FnParameters...)> {
struct override_aux<Function, FnReturnType (FnClass::*)(FnParameters...)> {
static auto fn(FnClass* this_, FnParameters&&... args) -> FnReturnType {
return (this_->*Function)(std::forward<FnParameters>(args)...);
}

override_impl<fn> impl{&next<Function>};
override_impl<fn, FnReturnType> impl{&next<Function>};
};

public:
Expand All @@ -692,18 +705,19 @@ constexpr bool is_method = std::is_base_of_v<detail::method_info, T>;

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

using virtual_type_ids = detail::type_id_list<
Policy,
boost::mp11::mp_transform_q<
boost::mp11::mp_bind_front<detail::polymorphic_type, Policy>,
VirtualParameters>>;
this->vp_begin = virtual_type_ids::begin;
this->vp_end = virtual_type_ids::end;
this->not_implemented = (void*)not_implemented_handler;
this->ambiguous = (void*)ambiguous_handler;
this->method_type = Policy::template static_type<method>();
method_info::vp_begin = virtual_type_ids::begin;
method_info::vp_end = virtual_type_ids::end;
method_info::not_implemented = (void*)not_implemented_handler;
method_info::method_type = Policy::template static_type<method>();
method_info::return_type = Policy::template static_type<
typename virtual_traits<Policy, Return>::polymorphic_type>();
Policy::methods.push_back(*this);
}

Expand Down Expand Up @@ -742,7 +756,7 @@ template<typename Name, typename Return, typename... Parameters, class Policy>
BOOST_FORCEINLINE auto method<Name(Parameters...), Return, Policy>::operator()(
detail::remove_virtual<Parameters>... args) const -> Return {
using namespace detail;
auto pf = resolve(argument_traits<Policy, Parameters>::rarg(args)...);
auto pf = resolve(parameter_traits<Policy, Parameters>::rarg(args)...);

return pf(std::forward<remove_virtual<Parameters>>(args)...);
}
Expand Down Expand Up @@ -926,30 +940,7 @@ method<Name(Parameters...), Return, Policy>::not_implemented_handler(
auto ti_iter = types;
(...,
(*ti_iter++ = Policy::dynamic_type(
detail::argument_traits<Policy, Parameters>::rarg(args))));
std::copy_n(
types, (std::min)(sizeof...(args), resolution_error::max_types),
&error.types[0]);
Policy::error(error);
}

abort(); // in case user handler "forgets" to abort
}

template<typename Name, typename Return, typename... Parameters, class Policy>
BOOST_NORETURN auto
method<Name(Parameters...), Return, Policy>::ambiguous_handler(
detail::remove_virtual<Parameters>... args) -> Return {
if constexpr (Policy::template has_facet<policies::error_handler>) {
resolution_error error;
error.status = resolution_error::ambiguous;
error.method = Policy::template static_type<method>();
error.arity = Arity;
type_id types[sizeof...(args)];
auto ti_iter = types;
(...,
(*ti_iter++ = Policy::dynamic_type(
detail::argument_traits<Policy, Parameters>::rarg(args))));
detail::parameter_traits<Policy, Parameters>::rarg(args))));
std::copy_n(
types, (std::min)(sizeof...(args), resolution_error::max_types),
&error.types[0]);
Expand All @@ -969,31 +960,35 @@ auto method<Name(Parameters...), Return, Policy>::
thunk<Overrider, OverriderReturn (*)(OverriderParameters...)>::fn(
detail::remove_virtual<Parameters>... arg) -> Return {
return Overrider(
detail::argument_traits<Policy, Parameters>::template cast<
detail::parameter_traits<Policy, Parameters>::template cast<
OverriderParameters>(detail::remove_virtual<Parameters>(arg))...);
}

// -----------------------------------------------------------------------------
// overriders

template<typename Name, typename Return, typename... Parameters, class Policy>
template<auto Function>
template<auto Function, typename FnReturnType>
method<Name(Parameters...), Return, Policy>::override_impl<
Function>::override_impl(FunctionPointer* p_next) {
Function, FnReturnType>::override_impl(FunctionPointer* p_next) {
using namespace detail;

// Work around MSVC bug: using &next<Function> as a default value
// for 'next' confuses it about Parameters not being expanded.
if (!p_next) {
p_next = &next<Function>;
}

static detail::overrider_info info;
static overrider_info info;

if (info.method) {
BOOST_ASSERT(info.method == &fn);
return;
}

info.method = &fn;
info.return_type = Policy::template static_type<
typename virtual_traits<Policy, FnReturnType>::polymorphic_type>();
info.type = Policy::template static_type<decltype(Function)>();
info.next = reinterpret_cast<void**>(p_next);
using Thunk = thunk<Function, decltype(Function)>;
Expand Down
3 changes: 1 addition & 2 deletions include/yorel/yomm2/decode.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,13 +77,12 @@ void decode_dispatch_data(Data& init) {
packed_slots_iter += slots_strides_count;

auto specs =
(uintptr_t*)alloca((method.specs.size() + 2) * pointer_size);
(uintptr_t*)alloca((method.specs.size() + 1) * pointer_size);
*method_defs_iter++ = specs;
++trace << "specs index: " << specs << "\n";
specs = std::transform(
method.specs.begin(), method.specs.end(), specs,
[](auto& spec) { return (uintptr_t)spec.pf; });
*specs++ = (uintptr_t)method.ambiguous;
*specs++ = (uintptr_t)method.not_implemented;
++method_index;
}
Expand Down
Loading

0 comments on commit 152d311

Please sign in to comment.