3333#endif
3434
3535namespace boost ::openmethod {
36+
37+ // ! N2216 ambiguity resolution.
38+ // !
39+ // ! If `n2216` is present in @ref initialize\'s `Options`, additional steps are
40+ // ! taken to select a single overrider in presence of ambiguous overriders sets,
41+ // ! according to the rules defined in the N2216 paper. If the normal resolution
42+ // ! procedure fails to select a single overrider, the following steps are
43+ // ! applied, in order:
44+ // !
45+ // ! - If the return types of the remaining overriders are all polymorphic and
46+ // ! covariant, and one of the return types is more specialized thjat all the
47+ // ! others, use it.
48+ // !
49+ // ! - Otherwise, pick one of the overriders. Which one is used is unspecified,
50+ // ! but remains the same throughtout the program, and across different runs of
51+ // ! the same program.
52+ struct n2216 ;
53+
3654namespace detail {
3755
3856template <class Reports , class Facets , typename = void >
@@ -244,10 +262,15 @@ auto operator<<(trace_type<Registry>& trace, const spec_name& sn)
244262
245263} // namespace detail
246264
265+ // Definition of the nested template struct outside the registry class
247266template <class ... Policies>
267+ template <class ... Options>
248268struct registry <Policies...>::compiler : detail::generic_compiler {
249269 using type_index_type = decltype (rtti::type_index(0 ));
250270
271+ static constexpr bool use_n2216 =
272+ mp11::mp_contains<mp11::mp_list<Options...>, n2216>::value;
273+
251274 typename detail::aggregate_reports<mp11::mp_list<report>, policy_list>::type
252275 report;
253276
@@ -285,7 +308,8 @@ struct registry<Policies...>::compiler : detail::generic_compiler {
285308};
286309
287310template <class ... Policies>
288- void registry<Policies...>::compiler::install_global_tables() {
311+ template <class ... Options>
312+ void registry<Policies...>::compiler<Options...>::install_global_tables() {
289313 if (!compilation_done) {
290314 abort ();
291315 }
@@ -297,7 +321,8 @@ void registry<Policies...>::compiler::install_global_tables() {
297321}
298322
299323template <class ... Policies>
300- auto registry<Policies...>::compiler::compile() {
324+ template <class ... Options>
325+ auto registry<Policies...>::compiler<Options...>::compile() {
301326 augment_classes ();
302327 augment_methods ();
303328 assign_slots ();
@@ -309,7 +334,8 @@ auto registry<Policies...>::compiler::compile() {
309334}
310335
311336template <class ... Policies>
312- auto registry<Policies...>::compiler::initialize() {
337+ template <class ... Options>
338+ auto registry<Policies...>::compiler<Options...>::initialize() {
313339 compile ();
314340 install_global_tables ();
315341
@@ -319,11 +345,13 @@ auto registry<Policies...>::compiler::initialize() {
319345}
320346
321347template <class ... Policies>
322- registry<Policies...>::compiler::compiler() {
348+ template <class ... Options>
349+ registry<Policies...>::compiler<Options...>::compiler() {
323350}
324351
325352template <class ... Policies>
326- void registry<Policies...>::compiler::collect_transitive_bases(
353+ template <class ... Options>
354+ void registry<Policies...>::compiler<Options...>::collect_transitive_bases(
327355 class_* cls, class_* base) {
328356 if (base->mark == class_mark) {
329357 return ;
@@ -338,7 +366,8 @@ void registry<Policies...>::compiler::collect_transitive_bases(
338366}
339367
340368template <class ... Policies>
341- void registry<Policies...>::compiler::augment_classes() {
369+ template <class ... Options>
370+ void registry<Policies...>::compiler<Options...>::augment_classes() {
342371 using namespace detail ;
343372
344373 // scope
@@ -479,7 +508,8 @@ void registry<Policies...>::compiler::augment_classes() {
479508}
480509
481510template <class ... Policies>
482- void registry<Policies...>::compiler::calculate_transitive_derived(
511+ template <class ... Options>
512+ void registry<Policies...>::compiler<Options...>::calculate_transitive_derived(
483513 class_& cls) {
484514 if (!cls.transitive_derived .empty ()) {
485515 return ;
@@ -501,7 +531,8 @@ void registry<Policies...>::compiler::calculate_transitive_derived(
501531}
502532
503533template <class ... Policies>
504- void registry<Policies...>::compiler::augment_methods() {
534+ template <class ... Options>
535+ void registry<Policies...>::compiler<Options...>::augment_methods() {
505536 using namespace policies ;
506537 using namespace detail ;
507538
@@ -663,7 +694,8 @@ void registry<Policies...>::compiler::augment_methods() {
663694}
664695
665696template <class ... Policies>
666- void registry<Policies...>::compiler::assign_slots() {
697+ template <class ... Options>
698+ void registry<Policies...>::compiler<Options...>::assign_slots() {
667699 ++trace << " Allocating slots...\n " ;
668700
669701 {
@@ -710,7 +742,8 @@ void registry<Policies...>::compiler::assign_slots() {
710742}
711743
712744template <class ... Policies>
713- void registry<Policies...>::compiler::assign_tree_slots(
745+ template <class ... Options>
746+ void registry<Policies...>::compiler<Options...>::assign_tree_slots(
714747 class_& cls, std::size_t base_slot) {
715748 auto next_slot = base_slot;
716749 using namespace detail ;
@@ -731,7 +764,9 @@ void registry<Policies...>::compiler::assign_tree_slots(
731764}
732765
733766template <class ... Policies>
734- void registry<Policies...>::compiler::assign_lattice_slots(class_& cls) {
767+ template <class ... Options>
768+ void registry<Policies...>::compiler<Options...>::assign_lattice_slots(
769+ class_& cls) {
735770 using namespace detail ;
736771
737772 if (cls.mark == class_mark) {
@@ -807,7 +842,8 @@ void registry<Policies...>::compiler::assign_lattice_slots(class_& cls) {
807842}
808843
809844template <class ... Policies>
810- void registry<Policies...>::compiler::build_dispatch_tables() {
845+ template <class ... Options>
846+ void registry<Policies...>::compiler<Options...>::build_dispatch_tables() {
811847 using namespace detail ;
812848
813849 for (auto & m : methods) {
@@ -934,7 +970,8 @@ void registry<Policies...>::compiler::build_dispatch_tables() {
934970}
935971
936972template <class ... Policies>
937- void registry<Policies...>::compiler::build_dispatch_table(
973+ template <class ... Options>
974+ void registry<Policies...>::compiler<Options...>::build_dispatch_table(
938975 method& m, std::size_t dim,
939976 std::vector<group_map>::const_iterator group_iter, const bitvec& candidates,
940977 bool concrete) {
@@ -987,7 +1024,7 @@ void registry<Policies...>::compiler::build_dispatch_table(
9871024 m.dispatch_table .push_back (&m.not_implemented );
9881025 ++m.report .not_implemented ;
9891026 } else {
990- if constexpr (!has_n2216 ) {
1027+ if constexpr (!use_n2216 ) {
9911028 if (remaining > 1 ) {
9921029 ++trace << " ambiguous\n " ;
9931030 m.dispatch_table .push_back (&m.ambiguous );
@@ -1048,7 +1085,7 @@ void registry<Policies...>::compiler::build_dispatch_table(
10481085
10491086 select_dominant_overriders (overriders, pick, remaining);
10501087
1051- if constexpr (!has_n2216 ) {
1088+ if constexpr (!use_n2216 ) {
10521089 if (remaining > 1 ) {
10531090 ++trace << " ambiguous 'next'\n " ;
10541091 overrider->next = &m.ambiguous ;
@@ -1089,7 +1126,8 @@ inline void detail::generic_compiler::accumulate(
10891126}
10901127
10911128template <class ... Policies>
1092- void registry<Policies...>::compiler::write_global_data() {
1129+ template <class ... Options>
1130+ void registry<Policies...>::compiler<Options...>::write_global_data() {
10931131 using namespace policies ;
10941132 using namespace detail ;
10951133
@@ -1210,7 +1248,8 @@ void registry<Policies...>::compiler::write_global_data() {
12101248}
12111249
12121250template <class ... Policies>
1213- void registry<Policies...>::compiler::select_dominant_overriders(
1251+ template <class ... Options>
1252+ void registry<Policies...>::compiler<Options...>::select_dominant_overriders(
12141253 std::vector<overrider*>& candidates, std::size_t & pick,
12151254 std::size_t & remaining) {
12161255
@@ -1241,7 +1280,7 @@ void registry<Policies...>::compiler::select_dominant_overriders(
12411280 return ;
12421281 }
12431282
1244- if constexpr (has_n2216 ) {
1283+ if constexpr (use_n2216 ) {
12451284 if (!candidates[pick]->covariant_return_type ) {
12461285 return ;
12471286 }
@@ -1276,7 +1315,8 @@ void registry<Policies...>::compiler::select_dominant_overriders(
12761315}
12771316
12781317template <class ... Policies>
1279- auto registry<Policies...>::compiler::is_more_specific(
1318+ template <class ... Options>
1319+ auto registry<Policies...>::compiler<Options...>::is_more_specific(
12801320 const overrider* a, const overrider* b) -> bool {
12811321 bool result = false ;
12821322
@@ -1299,7 +1339,8 @@ auto registry<Policies...>::compiler::is_more_specific(
12991339}
13001340
13011341template <class ... Policies>
1302- auto registry<Policies...>::compiler::is_base(
1342+ template <class ... Options>
1343+ auto registry<Policies...>::compiler<Options...>::is_base(
13031344 const overrider* a, const overrider* b) -> bool {
13041345 bool result = false ;
13051346
@@ -1320,7 +1361,9 @@ auto registry<Policies...>::compiler::is_base(
13201361}
13211362
13221363template <class ... Policies>
1323- void registry<Policies...>::compiler::print(const method_report& r) const {
1364+ template <class ... Options>
1365+ void registry<Policies...>::compiler<Options...>::print(
1366+ const method_report& r) const {
13241367 ++trace;
13251368
13261369 if (r.cells ) {
@@ -1332,7 +1375,7 @@ void registry<Policies...>::compiler::print(const method_report& r) const {
13321375 << " ambiguous\n " ;
13331376}
13341377
1335- template <class Registry >
1378+ template <class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY, class ... Options >
13361379auto initialize () {
13371380 if (odr_check<Registry>::count > 1 ) {
13381381 // Multiple definitions of default_registry detected.
@@ -1345,16 +1388,12 @@ auto initialize() {
13451388 std::abort ();
13461389 }
13471390
1348- typename Registry::compiler comp;
1391+ typename Registry::template compiler<Options...> comp;
13491392 comp.initialize ();
13501393
13511394 return comp;
13521395}
13531396
1354- // ! Initialize the default registry.
1355- inline auto initialize () {
1356- return initialize<BOOST_OPENMETHOD_DEFAULT_REGISTRY>();
1357- }
13581397
13591398namespace detail {
13601399
0 commit comments