Skip to content

Commit f7d47fb

Browse files
committed
pass compiler to policies' initialize()
1 parent e5762bd commit f7d47fb

File tree

7 files changed

+166
-168
lines changed

7 files changed

+166
-168
lines changed

include/boost/openmethod/core.hpp

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2792,10 +2792,6 @@ using boost::openmethod::virtual_ptr;
27922792

27932793
#ifdef __MRDOCS__
27942794

2795-
namespace detail {
2796-
struct unspecified;
2797-
}
2798-
27992795
//! Blueprint for a specialization of @ref virtual_traits (exposition only).
28002796
//!
28012797
//! Specializations of @ref virtual_traits must implement the members listed

include/boost/openmethod/initialize.hpp

Lines changed: 62 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -182,23 +182,30 @@ struct generic_compiler {
182182

183183
return nullptr;
184184
}
185+
185186
std::deque<class_> classes;
187+
188+
auto classes_begin() const {
189+
return classes.begin();
190+
}
191+
192+
auto classes_end() const {
193+
return classes.end();
194+
}
195+
186196
std::vector<method> methods;
187197
std::size_t class_mark = 0;
188198
bool compilation_done = false;
189199
};
190200

191201
template<class Compiler>
192202
struct trace_stream {
193-
trace_stream(bool trace) : trace(trace) {
194-
}
195-
196-
bool trace;
203+
bool on = false;
197204
std::size_t indentation_level{0};
198205

199206
auto operator++() -> trace_stream& {
200207
if constexpr (Compiler::has_trace) {
201-
if (trace) {
208+
if (on) {
202209
for (std::size_t i = 0; i < indentation_level; ++i) {
203210
Compiler::Registry::output::os << " ";
204211
}
@@ -296,7 +303,7 @@ struct range;
296303
template<class Compiler, typename T, typename F>
297304
auto write_range(trace_stream<Compiler>& tr, range<T> range, F fn) -> auto& {
298305
if constexpr (Compiler::has_trace) {
299-
if (tr.trace) {
306+
if (tr.on) {
300307
tr << "(";
301308
const char* sep = "";
302309
for (auto value : range) {
@@ -314,7 +321,7 @@ auto write_range(trace_stream<Compiler>& tr, range<T> range, F fn) -> auto& {
314321
template<class Compiler, typename T>
315322
auto operator<<(trace_stream<Compiler>& tr, const T& value) -> auto& {
316323
if constexpr (Compiler::has_trace) {
317-
if (tr.trace) {
324+
if (tr.on) {
318325
Compiler::Registry::output::os << value;
319326
}
320327
}
@@ -324,7 +331,7 @@ auto operator<<(trace_stream<Compiler>& tr, const T& value) -> auto& {
324331
template<class Compiler>
325332
auto operator<<(trace_stream<Compiler>& tr, const rflush& rf) -> auto& {
326333
if constexpr (Compiler::has_trace) {
327-
if (tr.trace) {
334+
if (tr.on) {
328335
std::size_t digits = 1;
329336
auto tmp = rf.value / 10;
330337

@@ -349,7 +356,7 @@ template<class Compiler>
349356
auto operator<<(trace_stream<Compiler>& tr, const boost::dynamic_bitset<>& bits)
350357
-> auto& {
351358
if constexpr (Compiler::has_trace) {
352-
if (tr.trace) {
359+
if (tr.on) {
353360
auto i = bits.size();
354361
while (i != 0) {
355362
--i;
@@ -388,9 +395,6 @@ template<class... Options>
388395
struct registry<Policies...>::compiler : detail::generic_compiler {
389396
using type_index_type = decltype(rtti::type_index(0));
390397

391-
static constexpr bool use_n2216 =
392-
mp11::mp_contains<mp11::mp_list<Options...>, n2216>::value;
393-
394398
typename detail::aggregate_reports<mp11::mp_list<report>, policy_list>::type
395399
report;
396400

@@ -425,10 +429,15 @@ struct registry<Policies...>::compiler : detail::generic_compiler {
425429
is_more_specific(const overrider* a, const overrider* b) -> bool;
426430
static auto is_base(const overrider* a, const overrider* b) -> bool;
427431

428-
std::tuple<Options...> opts;
429-
static constexpr bool has_trace =
430-
mp11::mp_contains<mp11::mp_list<Options...>, openmethod::trace>::value;
431-
bool trace = false;
432+
std::tuple<Options...> options;
433+
434+
template<class Option>
435+
static constexpr bool has_option =
436+
mp11::mp_contains<mp11::mp_list<Options...>, Option>::value;
437+
438+
static constexpr bool has_trace = has_option<trace>;
439+
static constexpr bool has_n2216 = has_option<n2216>;
440+
432441
mutable detail::trace_stream<compiler> tr;
433442
using indent = typename detail::trace_stream<compiler>::indent;
434443
};
@@ -467,11 +476,42 @@ void registry<Policies...>::compiler<Options...>::initialize() {
467476
registry<Policies...>::initialized = true;
468477
}
469478

479+
#ifdef _MSC_VER
480+
namespace detail {
481+
482+
template<bool HasTrace, typename T>
483+
struct msvc_tuple_get;
484+
485+
template<typename T>
486+
struct msvc_tuple_get<true, T> {
487+
template<class Tuple>
488+
static decltype(auto) fn(const Tuple& t) {
489+
return std::get<T>(t);
490+
}
491+
};
492+
493+
template<typename T>
494+
struct msvc_tuple_get<false, T> {
495+
template<class Tuple>
496+
static decltype(auto) fn(const Tuple&) {
497+
return T();
498+
}
499+
};
500+
} // namespace detail
501+
#endif
502+
470503
template<class... Policies>
471504
template<class... Options>
472505
registry<Policies...>::compiler<Options...>::compiler(Options... opts)
473-
: opts(opts...), trace(detail::option<openmethod::trace>(this->opts).on),
474-
tr(trace) {
506+
: options(opts...) {
507+
if constexpr (has_trace) {
508+
#ifdef _MSC_VER
509+
tr.on = detail::msvc_tuple_get<has_trace, trace>::fn(options).on;
510+
#else
511+
// Even with the constexpr has_trace guard, msvc errors on this.
512+
tr.on = std::get<trace>(options).on;
513+
#endif
514+
}
475515
}
476516

477517
template<class... Policies>
@@ -1148,7 +1188,7 @@ void registry<Policies...>::compiler<Options...>::build_dispatch_table(
11481188
m.dispatch_table.push_back(&m.not_implemented);
11491189
++m.report.not_implemented;
11501190
} else {
1151-
if constexpr (!use_n2216) {
1191+
if constexpr (!has_option<n2216>) {
11521192
if (remaining > 1) {
11531193
++tr << "ambiguous\n";
11541194
m.dispatch_table.push_back(&m.ambiguous);
@@ -1209,7 +1249,7 @@ void registry<Policies...>::compiler<Options...>::build_dispatch_table(
12091249

12101250
select_dominant_overriders(overriders, pick, remaining);
12111251

1212-
if constexpr (!use_n2216) {
1252+
if constexpr (!has_option<n2216>) {
12131253
if (remaining > 1) {
12141254
++tr << "ambiguous 'next'\n";
12151255
overrider->next = &m.ambiguous;
@@ -1368,7 +1408,7 @@ void registry<Policies...>::compiler<Options...>::write_global_data() {
13681408
++tr << rflush(4, dispatch_data_size) << " " << gv_iter << " end\n";
13691409

13701410
if constexpr (has_vptr) {
1371-
vptr::initialize(classes.begin(), classes.end(), opts);
1411+
vptr::initialize(*this, options);
13721412
}
13731413

13741414
new_dispatch_data.swap(dispatch_data);
@@ -1407,7 +1447,7 @@ void registry<Policies...>::compiler<Options...>::select_dominant_overriders(
14071447
return;
14081448
}
14091449

1410-
if constexpr (use_n2216) {
1450+
if constexpr (has_option<n2216>) {
14111451
if (!candidates[pick]->covariant_return_type) {
14121452
return;
14131453
}
@@ -1571,10 +1611,6 @@ void registry<Policies...>::compiler<Options...>::print(
15711611
//! @endcode
15721612
template<class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY, class... Options>
15731613
inline auto initialize(Options&&... options) {
1574-
static_assert(
1575-
(std::is_base_of_v<detail::option_base, Options> && ...),
1576-
"invalid option type");
1577-
15781614
if (detail::odr_check<Registry>::count > 1) {
15791615
// Multiple definitions of default_registry detected.
15801616
// This indicates an ODR violation.

include/boost/openmethod/policies/fast_perfect_hash.hpp

Lines changed: 29 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ struct fast_perfect_hash : type_hash {
8080

8181
static void check(std::size_t index, type_id type);
8282

83-
template<class ForwardIterator, class... Options>
83+
template<class InitializeContext, class... Options>
8484
static void initialize(
85-
ForwardIterator first, ForwardIterator last,
86-
std::vector<type_id>& buckets, std::tuple<Options...> options);
85+
const InitializeContext& ctx, std::vector<type_id>& buckets,
86+
const std::tuple<Options...>& options);
8787

8888
public:
8989
//! Find the hash factors
@@ -95,25 +95,18 @@ struct fast_perfect_hash : type_hash {
9595
//! If no suitable values are found, calls the error handler with
9696
//! a @ref hash_error object then calls `abort`.
9797
//!
98-
//! @tparam ForwardIterator An iterator to a range of @ref
99-
//! IdsToVptr objects.
100-
//! @tparam Options... Zero or more option types, deduced from the
101-
//! function arguments.
102-
//! @param first An iterator to the beginning of the range.
103-
//! @param last An iterator to the end of the range.
104-
//! @param options Zero or more option objects.
98+
//! @tparam Context An @ref InitializeContext.
99+
//! @param ctx A Context object.
105100
//! @return A pair containing the minimum and maximum hash values.
106-
template<class ForwardIterator, class... Options>
107-
static auto initialize(
108-
ForwardIterator first, ForwardIterator last,
109-
std::tuple<Options...> options) {
101+
template<class Context, class... Options>
102+
static auto
103+
initialize(const Context& ctx, const std::tuple<Options...>& options) {
110104
if constexpr (Registry::has_runtime_checks) {
111105
initialize(
112-
first, last, detail::fast_perfect_hash_control<Registry>,
113-
options);
106+
ctx, detail::fast_perfect_hash_control<Registry>, options);
114107
} else {
115108
std::vector<type_id> buckets;
116-
initialize(first, last, buckets, options);
109+
initialize(ctx, buckets, options);
117110
}
118111

119112
return std::pair{min_value, max_value};
@@ -150,7 +143,7 @@ struct fast_perfect_hash : type_hash {
150143
//! arguments.
151144
//! @param options Zero or more option objects.
152145
template<class... Options>
153-
static auto finalize(std::tuple<Options...>) -> void {
146+
static auto finalize(const std::tuple<Options...>&) -> void {
154147
detail::fast_perfect_hash_control<Registry>.clear();
155148
}
156149
};
@@ -169,21 +162,16 @@ template<class Registry>
169162
std::size_t fast_perfect_hash::fn<Registry>::max_value;
170163

171164
template<class Registry>
172-
template<class ForwardIterator, class... Options>
165+
template<class InitializeContext, class... Options>
173166
void fast_perfect_hash::fn<Registry>::initialize(
174-
ForwardIterator first, ForwardIterator last, std::vector<type_id>& buckets,
175-
std::tuple<Options...> opts) {
176-
using namespace policies;
177-
178-
const auto N = std::distance(first, last);
179-
(void)opts;
180-
181-
if constexpr (
182-
detail::has_option<trace, Options...> && Registry::has_output) {
183-
if (detail::option<trace>(opts).on) {
184-
Registry::output::os << "Finding hash factor for " << N
185-
<< " types\n";
186-
}
167+
const InitializeContext& ctx, std::vector<type_id>& buckets,
168+
const std::tuple<Options...>& options) {
169+
(void)options;
170+
171+
const auto N = std::distance(ctx.classes_begin(), ctx.classes_end());
172+
173+
if constexpr (mp11::mp_contains<mp11::mp_list<Options...>, trace>::value) {
174+
Registry::output::os << "Finding hash factor for " << N << " types\n";
187175
}
188176

189177
std::default_random_engine rnd(13081963);
@@ -202,13 +190,9 @@ void fast_perfect_hash::fn<Registry>::initialize(
202190
min_value = (std::numeric_limits<std::size_t>::max)();
203191
max_value = (std::numeric_limits<std::size_t>::min)();
204192

205-
if constexpr (
206-
mp11::mp_contains<mp11::mp_list<Options...>, trace>::value &&
207-
Registry::has_output) {
208-
if (detail::option<trace>(opts).on) {
209-
Registry::output::os << " trying with M = " << M << ", "
210-
<< hash_size << " buckets\n";
211-
}
193+
if constexpr (InitializeContext::template has_option<trace>) {
194+
ctx.tr << " trying with M = " << M << ", " << hash_size
195+
<< " buckets\n";
212196
}
213197

214198
std::size_t attempts = 0;
@@ -221,7 +205,8 @@ void fast_perfect_hash::fn<Registry>::initialize(
221205
++total_attempts;
222206
mult = uniform_dist(rnd) | 1;
223207

224-
for (auto iter = first; iter != last; ++iter) {
208+
for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
209+
++iter) {
225210
for (auto type_iter = iter->type_id_begin();
226211
type_iter != iter->type_id_end(); ++type_iter) {
227212
auto type = *type_iter;
@@ -238,15 +223,10 @@ void fast_perfect_hash::fn<Registry>::initialize(
238223
}
239224
}
240225

241-
if constexpr (
242-
mp11::mp_contains<mp11::mp_list<Options...>, trace>::value &&
243-
Registry::has_output) {
244-
if (detail::option<trace>(opts).on) {
245-
Registry::output::os
246-
<< " found " << mult << " after " << total_attempts
247-
<< " attempts; span = [" << min_value << ", "
248-
<< max_value << "]\n";
249-
}
226+
if constexpr (InitializeContext::template has_option<trace>) {
227+
ctx.tr << " found " << mult << " after " << total_attempts
228+
<< " attempts; span = [" << min_value << ", "
229+
<< max_value << "]\n";
250230
}
251231

252232
return;

include/boost/openmethod/policies/vptr_map.hpp

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,17 @@ class vptr_map : public vptr {
3838
public:
3939
//! Stores the v-table pointers.
4040
//!
41-
//! @tparam ForwardIterator An iterator to a range of @ref
42-
//! IdsToVptr objects.
43-
//! @tparam Options... Zero or more option types, deduced from the
44-
//! function arguments.
45-
//! @param first An iterator to the beginning of the range.
46-
//! @param last An iterator to the end of the range.
47-
//! @param options Zero or more option objects.
48-
template<class ForwardIterator, class... Options>
49-
static void initialize(
50-
ForwardIterator first, ForwardIterator last,
51-
std::tuple<Options...>) {
41+
//! @tparam Context An @ref InitializeContext.
42+
//! @tparam Options... Zero or more option types.
43+
//! @param ctx A Context object.
44+
//! @param options A tuple of option objects.
45+
template<class Context, class... Options>
46+
static void
47+
initialize(const Context& ctx, const std::tuple<Options...>&) {
5248
decltype(vptrs) new_vptrs;
5349

54-
for (auto iter = first; iter != last; ++iter) {
50+
for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
51+
++iter) {
5552
for (auto type_iter = iter->type_id_begin();
5653
type_iter != iter->type_id_end(); ++type_iter) {
5754

@@ -109,11 +106,11 @@ class vptr_map : public vptr {
109106

110107
//! Clears the map.
111108
//!
112-
//! @tparam Options... Zero or more option types, deduced from the
113-
//! function arguments.
114-
//! @param options Zero or more option objects.
109+
//! @tparam Options... Zero or more option types.
110+
//! @param ctx A Context object.
111+
//! @param options A tuple of option objects.
115112
template<class... Options>
116-
static auto finalize(std::tuple<Options...>) -> void {
113+
static auto finalize(const std::tuple<Options...>&) -> void {
117114
vptrs.clear();
118115
}
119116
};

0 commit comments

Comments
 (0)