@@ -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
191201template <class Compiler >
192202struct 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;
296303template <class Compiler , typename T, typename F>
297304auto 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& {
314321template <class Compiler , typename T>
315322auto 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& {
324331template <class Compiler >
325332auto 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>
349356auto 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>
388395struct 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+
470503template <class ... Policies>
471504template <class ... Options>
472505registry<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
477517template <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
15721612template <class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY, class ... Options>
15731613inline 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.
0 commit comments