Skip to content

Commit 7a5e9bc

Browse files
committed
make n2216 an option to 'initialize', not a policy
1 parent 2ae10eb commit 7a5e9bc

File tree

4 files changed

+85
-77
lines changed

4 files changed

+85
-77
lines changed

include/boost/openmethod/core.hpp

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,8 +2068,8 @@ struct validate_method_parameter<
20682068
//!
20692069
//! @par N2216 Handling of Ambiguous Calls
20702070
//!
2071-
//! If `Registry` contains the @ref n2216 policy, ambiguous calls are not an
2072-
//! error. Instead, the following extra steps are taken to select an
2071+
//! If `Registry` was initialized with the @ref N2216 option, ambiguous calls
2072+
//! are not an error. Instead, the following extra steps are taken to select an
20732073
//! overrider:
20742074
//!
20752075
//! 1. If the return type is a registered polymorphic type, remove all the
@@ -2352,12 +2352,7 @@ method<Id, ReturnType(Parameters...), Registry>::method() {
23522352
this->vp_begin = vp_type_ids;
23532353
this->vp_end = vp_type_ids + Arity;
23542354
this->not_implemented = reinterpret_cast<void (*)()>(fn_not_implemented);
2355-
2356-
if constexpr (Registry::has_n2216) {
2357-
this->ambiguous = nullptr;
2358-
} else {
2359-
this->ambiguous = reinterpret_cast<void (*)()>(fn_ambiguous);
2360-
}
2355+
this->ambiguous = reinterpret_cast<void (*)()>(fn_ambiguous);
23612356

23622357
Registry::methods.push_back(*this);
23632358
}
@@ -2528,10 +2523,8 @@ method<Id, ReturnType(Parameters...), Registry>::has_next() -> bool {
25282523
return false;
25292524
}
25302525

2531-
if constexpr (!Registry::has_n2216) {
2532-
if (next<Fn> == fn_ambiguous) {
2533-
return false;
2534-
}
2526+
if (next<Fn> == fn_ambiguous) {
2527+
return false;
25352528
}
25362529

25372530
return true;

include/boost/openmethod/initialize.hpp

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@
3333
#endif
3434

3535
namespace 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+
3654
namespace detail {
3755

3856
template<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
247266
template<class... Policies>
267+
template<class... Options>
248268
struct 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

287310
template<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

299323
template<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

311336
template<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

321347
template<class... Policies>
322-
registry<Policies...>::compiler::compiler() {
348+
template<class... Options>
349+
registry<Policies...>::compiler<Options...>::compiler() {
323350
}
324351

325352
template<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

340368
template<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

481510
template<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

503533
template<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

665696
template<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

712744
template<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

733766
template<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

809844
template<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

936972
template<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

10911128
template<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

12121250
template<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

12781317
template<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

13011341
template<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

13221363
template<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>
13361379
auto 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

13591398
namespace detail {
13601399

include/boost/openmethod/registry.hpp

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -717,27 +717,6 @@ struct runtime_checks final {
717717
struct fn {};
718718
};
719719

720-
//! Policy for N2216 ambiguity resolution.
721-
//!
722-
//! If this policy is present, additional steps are taken to select a single
723-
//! overrider in presence of ambiguous overriders sets, according to the rules
724-
//! defined in the N2216 paper. If the normal resolution procedure fails to
725-
//! select a single overrider, the following steps are applied, in order:
726-
//!
727-
//! - If the return types of the remaining overriders are all polymorphic and
728-
//! covariant, and one of the return types is more specialized thjat all the
729-
//! others, use it.
730-
//!
731-
//! - Otherwise, pick one of the overriders. Which one is used is unspecified,
732-
//! but remains the same throughtout the program, and across different runs of
733-
//! the same program.
734-
struct n2216 final {
735-
// Policy category.
736-
using category = n2216;
737-
template<class Registry>
738-
struct fn {};
739-
};
740-
741720
} // namespace policies
742721

743722
namespace detail {
@@ -811,7 +790,7 @@ struct use_class_aux;
811790

812791
} // namespace detail
813792

814-
template<class Registry>
793+
template<class Registry, class...>
815794
auto initialize();
816795

817796
//! A collection of methods, classes and policies.
@@ -877,6 +856,7 @@ class registry : detail::registry_base {
877856
inline static bool initialized;
878857

879858
protected:
859+
template<class... Options>
880860
struct compiler;
881861

882862
public:
@@ -899,7 +879,7 @@ class registry : detail::registry_base {
899879
//! not registered.
900880
//!
901881
//! In addition, policies may encounter and report errors.
902-
template<class Registry>
882+
template<class Registry, class...>
903883
friend auto initialize();
904884

905885
//! Checks if the registry is initialized.
@@ -1015,10 +995,6 @@ class registry : detail::registry_base {
1015995
//! `true` if the registry has an indirect_vptr policy.
1016996
static constexpr auto has_indirect_vptr =
1017997
!std::is_same_v<policy<policies::indirect_vptr>, void>;
1018-
1019-
//! `true` if the registry has a n2216 policy.
1020-
static constexpr auto has_n2216 =
1021-
!std::is_same_v<policy<policies::n2216>, void>;
1022998
};
1023999

10241000
template<class... Policies>

0 commit comments

Comments
 (0)