Skip to content

Commit e19e34b

Browse files
committed
generalize initialization of policies
1 parent 1a70b0f commit e19e34b

File tree

6 files changed

+98
-21
lines changed

6 files changed

+98
-21
lines changed

include/boost/openmethod/default_registry.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,8 @@ struct default_registry_attributes {};
3939
//! including those pulled from libraries.
4040
struct default_registry
4141
: registry<
42-
policies::std_rtti, policies ::vptr_vector,
43-
policies::fast_perfect_hash, policies::default_error_handler,
42+
policies::std_rtti, policies::fast_perfect_hash,
43+
policies::vptr_vector, policies::default_error_handler,
4444
policies::stderr_output,
4545
policies::attributes_guide<default_registry_attributes>
4646
#ifdef BOOST_OPENMETHOD_ENABLE_RUNTIME_CHECKS

include/boost/openmethod/initialize.hpp

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,65 @@ struct aggregate_reports<mp11::mp_list<Reports...>, mp11::mp_list<>, Void> {
5959
struct type : Reports... {};
6060
};
6161

62+
// Policy initialization helpers
63+
64+
// Detect if a policy fn has an initialize function with the expected signature
65+
template<typename PolicyFn, typename Context, typename Options, typename = void>
66+
struct has_initialize : std::false_type {};
67+
68+
#if defined(_MSC_VER) && _MSC_VER <= 1950
69+
template<typename PolicyFn, typename Context, typename Options>
70+
struct has_initialize<
71+
PolicyFn, Context, Options,
72+
std::void_t<
73+
decltype(&PolicyFn::template initialize<Context, Options>)>>
74+
: std::true_type {};
75+
#else
76+
template<typename PolicyFn, typename Context, typename Options>
77+
struct has_initialize<
78+
PolicyFn, Context, Options,
79+
std::void_t<decltype(PolicyFn::initialize(
80+
std::declval<const Context&>(), std::declval<const Options&>()))>>
81+
: std::true_type {};
82+
#endif
83+
84+
// Call initialize on a single policy if it has the function
85+
template<typename Policy, typename Registry, typename Context, typename Options>
86+
void initialize_policy(const Context& ctx, const Options& options) {
87+
using PolicyFn = typename Policy::template fn<Registry>;
88+
if constexpr (has_initialize<PolicyFn, Context, Options>::value) {
89+
PolicyFn::initialize(ctx, options);
90+
}
91+
}
92+
93+
template<typename Registry, typename Policies = typename Registry::policy_list>
94+
struct initialize_policies;
95+
96+
template<typename Registry, typename... Policies>
97+
struct initialize_policies<Registry, mp11::mp_list<Policies...>> {
98+
template<typename Context, typename Options>
99+
static void fn(const Context& ctx, const Options& options) {
100+
(initialize_policy<Policies, Registry>(ctx, options), ...);
101+
}
102+
};
103+
104+
// template<typename Registry, typename Policy, typename... Policies>
105+
// struct initialize_policies<Registry, mp11::mp_list<Policy, Policies...>> {
106+
// template<typename Context, typename Options>
107+
// static void fn(const Context& ctx, const Options& options) {
108+
// initialize_policy<Policy, Registry>(ctx, options);
109+
// initialize_policies<Registry, mp11::mp_list<Policies...>>::fn(
110+
// ctx, options);
111+
// }
112+
// };
113+
114+
// template<typename Registry>
115+
// struct initialize_policies<Registry, mp11::mp_list<>> {
116+
// template<typename Context, typename Options>
117+
// static void fn(const Context& ctx, const Options& options) {
118+
// }
119+
// };
120+
62121
inline void merge_into(boost::dynamic_bitset<>& a, boost::dynamic_bitset<>& b) {
63122
if (b.size() < a.size()) {
64123
b.resize(a.size());
@@ -438,8 +497,8 @@ struct registry<Policies...>::compiler : detail::generic_compiler {
438497
static void select_dominant_overriders(
439498
std::vector<overrider*>& dominants, std::size_t& pick,
440499
std::size_t& remaining);
441-
static auto
442-
is_more_specific(const overrider* a, const overrider* b) -> bool;
500+
static auto is_more_specific(const overrider* a, const overrider* b)
501+
-> bool;
443502
static auto is_base(const overrider* a, const overrider* b) -> bool;
444503

445504
std::tuple<Options...> options;
@@ -1420,9 +1479,7 @@ void registry<Policies...>::compiler<Options...>::write_global_data() {
14201479

14211480
++tr << rflush(4, dispatch_data_size) << " " << gv_iter << " end\n";
14221481

1423-
if constexpr (has_vptr) {
1424-
vptr::initialize(*this, options);
1425-
}
1482+
detail::initialize_policies<registry>::fn(*this, options);
14261483

14271484
new_dispatch_data.swap(storage::st.dispatch_data);
14281485
}

include/boost/openmethod/policies/default_error_handler.hpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,9 @@ struct default_error_handler : error_handler {
9595
//! @param error The error object.
9696
template<class Error>
9797
static auto error(const Error& error) -> void {
98-
handler_storage::handler(error_variant(error));
98+
auto handler = handler_storage::handler ? handler_storage::handler
99+
: default_handler;
100+
handler(error_variant(error));
99101
}
100102

101103
//! Sets the function to be called to handle errors.
@@ -107,8 +109,9 @@ struct default_error_handler : error_handler {
107109
//! @return The previous function.
108110
// coverity[auto_causes_copy]
109111
static auto set(function_type new_handler) -> function_type {
110-
return std::exchange(
112+
auto prev = std::exchange(
111113
handler_storage::handler, std::move(new_handler));
114+
return prev ? prev : default_handler;
112115
}
113116

114117
//! The default error handler function.

include/boost/openmethod/policies/fast_perfect_hash.hpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#include <limits>
1212
#include <random>
13+
#include <variant>
1314
#ifdef _MSC_VER
1415
#pragma warning(push)
1516
#pragma warning(disable : 4702) // unreachable code
@@ -92,12 +93,12 @@ struct fast_perfect_hash : type_hash {
9293
static void check(std::size_t index, type_id type);
9394

9495
template<class InitializeContext, class... Options>
95-
static void initialize(
96+
static void initialize_aux(
9697
const InitializeContext& ctx, std::vector<type_id>& buckets,
9798
const std::tuple<Options...>& options);
9899

99100
public:
100-
//! Find the hash factors
101+
//! Finds the hash factors
101102
//!
102103
//! Attempts to find suitable values for the multiplication factor `M`
103104
//! and the shift amount `S` to that do not result in collisions for the
@@ -111,15 +112,21 @@ struct fast_perfect_hash : type_hash {
111112
//! @return A pair containing the minimum and maximum hash values.
112113
template<class Context, class... Options>
113114
static auto
114-
initialize(const Context& ctx, const std::tuple<Options...>& options) {
115+
initialize(const Context& ctx, const std::tuple<Options...>& options)
116+
-> void {
115117
if constexpr (Registry::has_runtime_checks) {
116-
initialize(
118+
initialize_aux(
117119
ctx, detail::fast_perfect_hash_control<Registry>, options);
118120
} else {
119121
std::vector<type_id> buckets;
120-
initialize(ctx, buckets, options);
122+
initialize_aux(ctx, buckets, options);
121123
}
124+
}
122125

126+
//! Returns the hash range
127+
//!
128+
//! @return A pair containing the minimum and maximum hash values.
129+
static auto hash_range() -> std::pair<std::size_t, std::size_t> {
123130
return std::pair{
124131
factors_storage::hash_fn.min_value,
125132
factors_storage::hash_fn.max_value};
@@ -163,7 +170,7 @@ struct fast_perfect_hash : type_hash {
163170

164171
template<class Registry>
165172
template<class InitializeContext, class... Options>
166-
void fast_perfect_hash::fn<Registry>::initialize(
173+
void fast_perfect_hash::fn<Registry>::initialize_aux(
167174
const InitializeContext& ctx, std::vector<type_id>& buckets,
168175
const std::tuple<Options...>& options) {
169176
(void)options;

include/boost/openmethod/policies/vptr_vector.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ namespace boost::openmethod {
1616
namespace detail {
1717

1818
BOOST_OPENMETHOD_DETAIL_MAKE_SYMBOL_WITH_ATTRIBUTES(vptr_vector_vptrs);
19-
BOOST_OPENMETHOD_DETAIL_MAKE_SYMBOL_WITH_ATTRIBUTES(
20-
vptr_vector_indirect_vptrs);
19+
BOOST_OPENMETHOD_DETAIL_MAKE_SYMBOL_WITH_ATTRIBUTES(vptr_vector_indirect_vptrs);
2120

2221
} // namespace detail
2322

@@ -67,13 +66,14 @@ struct vptr_vector : vptr {
6766
//! @param ctx A Context object.
6867
//! @param options A tuple of option objects.
6968
template<class Context, class... Options>
70-
static auto initialize(
71-
const Context& ctx, const std::tuple<Options...>& options) -> void {
69+
static auto
70+
initialize(const Context& ctx, const std::tuple<Options...>& options)
71+
-> void {
7272
std::size_t size;
7373
(void)options;
7474

7575
if constexpr (has_type_hash) {
76-
auto [_, max_value] = type_hash::initialize(ctx, options);
76+
auto [_, max_value] = type_hash::hash_range();
7777
size = max_value + 1;
7878
} else {
7979
size = 0;
@@ -168,7 +168,7 @@ struct vptr_vector : vptr {
168168

169169
if constexpr (Registry::has_indirect_vptr) {
170170
return *indirect_vptrs_storage::vptr_vector_indirect_vptrs
171-
[index];
171+
[index];
172172
} else {
173173
return vptrs_storage::vptr_vector_vptrs[index];
174174
}

test/test_policies.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,3 +70,13 @@ BOOST_AUTO_TEST_CASE(test_registry) {
7070
BOOST_TEST(&registry2::static_vptr<void> != &registry1::static_vptr<void>);
7171
// BOOST_TEST(&registry2::dispatch_data != &registry1::dispatch_data);
7272
}
73+
74+
static_assert(has_initialize<
75+
vptr_vector::fn<registry1>, registry1::compiler<std::tuple<>>,
76+
std::tuple<>>::value);
77+
static_assert(!has_initialize<
78+
std_rtti::fn<registry1>, registry1::compiler<std::tuple<>>,
79+
std::tuple<>>::value);
80+
static_assert(has_initialize<
81+
fast_perfect_hash::fn<registry1>,
82+
registry1::compiler<std::tuple<>>, std::tuple<>>::value);

0 commit comments

Comments
 (0)