Skip to content

Commit acb1322

Browse files
committed
rework initialize
1 parent 91a0bb4 commit acb1322

File tree

2 files changed

+77
-56
lines changed

2 files changed

+77
-56
lines changed

include/boost/openmethod/initialize.hpp

Lines changed: 69 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,6 @@
3434

3535
namespace boost::openmethod {
3636

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-
5437
namespace detail {
5538

5639
template<class Reports, class Facets, typename = void>
@@ -260,8 +243,27 @@ auto operator<<(trace_type<Registry>& trace, const spec_name& sn)
260243
return trace;
261244
}
262245

246+
struct option_base {};
247+
263248
} // namespace detail
264249

250+
//! N2216 ambiguity resolution.
251+
//!
252+
//! If `n2216` is present in @ref initialize\'s `Options`, additional steps are
253+
//! taken to select a single overrider in presence of ambiguous overriders sets,
254+
//! according to the rules defined in the N2216 paper. If the normal resolution
255+
//! procedure fails to select a single overrider, the following steps are
256+
//! applied, in order:
257+
//!
258+
//! - If the return types of the remaining overriders are all polymorphic and
259+
//! covariant, and one of the return types is more specialized thjat all the
260+
//! others, use it.
261+
//!
262+
//! - Otherwise, pick one of the overriders. Which one is used is unspecified,
263+
//! but remains the same throughtout the program, and across different runs of
264+
//! the same program.
265+
struct n2216 : detail::option_base {};
266+
265267
// Definition of the nested template struct outside the registry class
266268
template<class... Policies>
267269
template<class... Options>
@@ -1375,26 +1377,62 @@ void registry<Policies...>::compiler<Options...>::print(
13751377
<< " ambiguous\n";
13761378
}
13771379

1378-
template<class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY, class... Options>
1379-
auto initialize() {
1380-
if (odr_check<Registry>::count > 1) {
1381-
// Multiple definitions of default_registry detected.
1382-
// This indicates an ODR violation.
1383-
// Signal a final_error using the error handler, then abort.
1384-
if constexpr (Registry::has_error_handler) {
1385-
Registry::error_handler::error(odr_violation());
1380+
namespace detail {
1381+
template<typename T, class... Options>
1382+
struct initialize_aux
1383+
: initialize_aux<T, BOOST_OPENMETHOD_DEFAULT_REGISTRY, Options...> {};
1384+
1385+
template<class Registry, class... Options>
1386+
struct initialize_aux<
1387+
std::void_t<typename Registry::registry_type>, Registry, Options...> {
1388+
static_assert(
1389+
(std::is_base_of_v<detail::option_base, Options> && ...),
1390+
"invalid option type");
1391+
static auto fn() {
1392+
if (odr_check<Registry>::count > 1) {
1393+
// Multiple definitions of default_registry detected.
1394+
// This indicates an ODR violation.
1395+
// Signal a final_error using the error handler, then abort.
1396+
if constexpr (Registry::has_error_handler) {
1397+
Registry::error_handler::error(odr_violation());
1398+
}
1399+
1400+
std::abort();
13861401
}
13871402

1388-
std::abort();
1389-
}
1403+
typename Registry::template compiler<Options...> comp;
1404+
comp.initialize();
13901405

1391-
typename Registry::template compiler<Options...> comp;
1392-
comp.initialize();
1406+
return comp;
1407+
}
1408+
};
1409+
} // namespace detail
13931410

1394-
return comp;
1411+
//! Initialize a registry.
1412+
//!
1413+
//! `initialize` must be called, typically at the beginning of `main`, before
1414+
//! using any of the methods in a registry. It sets up the v-tables,
1415+
//! multi-method dispatch tables, and any other data required by the policies.
1416+
//!
1417+
//! If the first template argument is a registry, initialize it. Otherwise,
1418+
//! initialize the default registry. Additional template arguments, if any, must
1419+
//! be option types (@ref n2216 or @ref enable_trace).
1420+
//!
1421+
//! @note
1422+
//! A translation unit that contains a call to `initialize` must include the
1423+
//! `<boost/openmethod/initialize.hpp>` header.
1424+
//!
1425+
//! @par Errors
1426+
//!
1427+
//! @li @ref missing_class: A class used in a virtual parameter was
1428+
//! not registered.
1429+
//!
1430+
//! @li Errors reported by the policies.
1431+
template<class... T>
1432+
inline auto initialize() {
1433+
return detail::initialize_aux<void, T...>::fn();
13951434
}
13961435

1397-
13981436
namespace detail {
13991437

14001438
template<class Policy, typename = void>

include/boost/openmethod/registry.hpp

Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ struct odr_check {
9292
inline static std::size_t inc = count++;
9393

9494
odr_check() {
95-
[[maybe_unused]] auto _ = &inc<typename Registry::self_type>;
95+
[[maybe_unused]] auto _ = &inc<typename Registry::registry_type>;
9696
}
9797
};
9898

@@ -788,10 +788,10 @@ struct without_aux<Policies, Policy, MorePolicies...> {
788788
template<class...>
789789
struct use_class_aux;
790790

791-
} // namespace detail
791+
template<typename, class...>
792+
struct initialize_aux;
792793

793-
template<class Registry, class...>
794-
auto initialize();
794+
} // namespace detail
795795

796796
//! A collection of methods, classes and policies.
797797
//!
@@ -856,31 +856,14 @@ class registry : detail::registry_base {
856856
inline static bool initialized;
857857

858858
protected:
859-
template<class... Options>
859+
template<class... Options>
860860
struct compiler;
861861

862862
public:
863-
using self_type = registry;
863+
using registry_type = registry;
864864

865-
//! Initializes the registry.
866-
//!
867-
//! `initialize` must be called, typically at the beginning of `main`,
868-
//! before using any of the methods in the registry. It sets up the
869-
//! v-tables, multi-method dispatch tables, and any other data required by
870-
//! the policies.
871-
//!
872-
//! @note
873-
//! A translation unit that contains a call to `initialize` must include the
874-
//! `<boost/openmethod/initialize.hpp>` header.
875-
//!
876-
//! @par Errors
877-
//!
878-
//! @li @ref missing_class: A class used in a virtual parameter was
879-
//! not registered.
880-
//!
881-
//! In addition, policies may encounter and report errors.
882-
template<class Registry, class...>
883-
friend auto initialize();
865+
template<typename, class...>
866+
friend struct detail::initialize_aux;
884867

885868
//! Checks if the registry is initialized.
886869
//!

0 commit comments

Comments
 (0)