#include #include #include #include #include #include #include #include #include #include using namespace boost::openmethod; template constexpr bool is_any = false; template constexpr bool is_any> = true; struct type_erased_rtti : policies::rtti { template static constexpr auto is_polymorphic = is_any; template static type_id static_type() { if constexpr (is_any) { return reinterpret_cast(&typeid(void)); } else { return reinterpret_cast(&typeid(T)); } } template static type_id dynamic_type(const T &obj) { return reinterpret_cast(&boost::type_erasure::typeid_of(obj)); } template static void type_name(type_id type, Stream &stream) { stream << reinterpret_cast(type)->name(); } static std::type_index type_index(type_id type) { return std::type_index(*reinterpret_cast(type)); } template static D dynamic_cast_ref(B &&obj) { // cast through void* for a fast, unchecked cast using unref = std::remove_reference_t; if constexpr (std::is_const_v) { return *static_cast( boost::type_erasure::any_cast(&obj)); } else { return *static_cast(boost::type_erasure::any_cast(&obj)); } } }; struct type_erased_policy : boost::openmethod::policies::debug::fork::replace< boost::openmethod::policies::rtti, type_erased_rtti> {}; BOOST_OPENMETHOD_CLASSES(void, type_erased_policy) template boost::openmethod::detail::class_declaration_aux< Policy, boost::mp11::mp_list> global_register; template struct openmethod_vptr { static boost::openmethod::vptr_type apply(const T &) { const auto &_ = global_register; return Policy::template static_vptr; } }; namespace boost::type_erasure { template struct concept_interface<::openmethod_vptr, Base, T> : Base { friend boost::openmethod::vptr_type boost_openmethod_vptr( const typename boost::type_erasure::derived::type &arg) { return boost::type_erasure::call(::openmethod_vptr(), arg); } }; } // namespace boost::type_erasure template using openmethod = boost::mp11::mp_list, openmethod_vptr>; using Base = boost::type_erasure::any, boost::type_erasure::copy_constructible<>>>; using BaseRef = boost::type_erasure::any, boost::type_erasure::_self &>; BOOST_OPENMETHOD(foo, (virtual_), void, type_erased_policy) BOOST_OPENMETHOD_OVERRIDE(foo, (int &i), void) { i = 5; } BOOST_OPENMETHOD_OVERRIDE(foo, (double &d), void) { d = 2.718; } int main() { boost::openmethod::initialize(); int i = 0; double d = 0; BaseRef b1(i); BaseRef b2(d); foo(b1); foo(b2); std::cout << i << std::endl; std::cout << d << std::endl; Base b3(42); foo(b3); std::cout << any_cast(b3) << std::endl; }