mirror of
https://github.com/boostorg/openmethod.git
synced 2026-01-19 04:22:12 +00:00
pass compiler to policies' initialize()
This commit is contained in:
@@ -2792,10 +2792,6 @@ using boost::openmethod::virtual_ptr;
|
||||
|
||||
#ifdef __MRDOCS__
|
||||
|
||||
namespace detail {
|
||||
struct unspecified;
|
||||
}
|
||||
|
||||
//! Blueprint for a specialization of @ref virtual_traits (exposition only).
|
||||
//!
|
||||
//! Specializations of @ref virtual_traits must implement the members listed
|
||||
|
||||
@@ -182,7 +182,17 @@ struct generic_compiler {
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::deque<class_> classes;
|
||||
|
||||
auto classes_begin() const {
|
||||
return classes.begin();
|
||||
}
|
||||
|
||||
auto classes_end() const {
|
||||
return classes.end();
|
||||
}
|
||||
|
||||
std::vector<method> methods;
|
||||
std::size_t class_mark = 0;
|
||||
bool compilation_done = false;
|
||||
@@ -190,15 +200,12 @@ struct generic_compiler {
|
||||
|
||||
template<class Compiler>
|
||||
struct trace_stream {
|
||||
trace_stream(bool trace) : trace(trace) {
|
||||
}
|
||||
|
||||
bool trace;
|
||||
bool on = false;
|
||||
std::size_t indentation_level{0};
|
||||
|
||||
auto operator++() -> trace_stream& {
|
||||
if constexpr (Compiler::has_trace) {
|
||||
if (trace) {
|
||||
if (on) {
|
||||
for (std::size_t i = 0; i < indentation_level; ++i) {
|
||||
Compiler::Registry::output::os << " ";
|
||||
}
|
||||
@@ -296,7 +303,7 @@ struct range;
|
||||
template<class Compiler, typename T, typename F>
|
||||
auto write_range(trace_stream<Compiler>& tr, range<T> range, F fn) -> auto& {
|
||||
if constexpr (Compiler::has_trace) {
|
||||
if (tr.trace) {
|
||||
if (tr.on) {
|
||||
tr << "(";
|
||||
const char* sep = "";
|
||||
for (auto value : range) {
|
||||
@@ -314,7 +321,7 @@ auto write_range(trace_stream<Compiler>& tr, range<T> range, F fn) -> auto& {
|
||||
template<class Compiler, typename T>
|
||||
auto operator<<(trace_stream<Compiler>& tr, const T& value) -> auto& {
|
||||
if constexpr (Compiler::has_trace) {
|
||||
if (tr.trace) {
|
||||
if (tr.on) {
|
||||
Compiler::Registry::output::os << value;
|
||||
}
|
||||
}
|
||||
@@ -324,7 +331,7 @@ auto operator<<(trace_stream<Compiler>& tr, const T& value) -> auto& {
|
||||
template<class Compiler>
|
||||
auto operator<<(trace_stream<Compiler>& tr, const rflush& rf) -> auto& {
|
||||
if constexpr (Compiler::has_trace) {
|
||||
if (tr.trace) {
|
||||
if (tr.on) {
|
||||
std::size_t digits = 1;
|
||||
auto tmp = rf.value / 10;
|
||||
|
||||
@@ -349,7 +356,7 @@ template<class Compiler>
|
||||
auto operator<<(trace_stream<Compiler>& tr, const boost::dynamic_bitset<>& bits)
|
||||
-> auto& {
|
||||
if constexpr (Compiler::has_trace) {
|
||||
if (tr.trace) {
|
||||
if (tr.on) {
|
||||
auto i = bits.size();
|
||||
while (i != 0) {
|
||||
--i;
|
||||
@@ -388,9 +395,6 @@ template<class... Options>
|
||||
struct registry<Policies...>::compiler : detail::generic_compiler {
|
||||
using type_index_type = decltype(rtti::type_index(0));
|
||||
|
||||
static constexpr bool use_n2216 =
|
||||
mp11::mp_contains<mp11::mp_list<Options...>, n2216>::value;
|
||||
|
||||
typename detail::aggregate_reports<mp11::mp_list<report>, policy_list>::type
|
||||
report;
|
||||
|
||||
@@ -425,10 +429,15 @@ struct registry<Policies...>::compiler : detail::generic_compiler {
|
||||
is_more_specific(const overrider* a, const overrider* b) -> bool;
|
||||
static auto is_base(const overrider* a, const overrider* b) -> bool;
|
||||
|
||||
std::tuple<Options...> opts;
|
||||
static constexpr bool has_trace =
|
||||
mp11::mp_contains<mp11::mp_list<Options...>, openmethod::trace>::value;
|
||||
bool trace = false;
|
||||
std::tuple<Options...> options;
|
||||
|
||||
template<class Option>
|
||||
static constexpr bool has_option =
|
||||
mp11::mp_contains<mp11::mp_list<Options...>, Option>::value;
|
||||
|
||||
static constexpr bool has_trace = has_option<trace>;
|
||||
static constexpr bool has_n2216 = has_option<n2216>;
|
||||
|
||||
mutable detail::trace_stream<compiler> tr;
|
||||
using indent = typename detail::trace_stream<compiler>::indent;
|
||||
};
|
||||
@@ -467,11 +476,42 @@ void registry<Policies...>::compiler<Options...>::initialize() {
|
||||
registry<Policies...>::initialized = true;
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
namespace detail {
|
||||
|
||||
template<bool HasTrace, typename T>
|
||||
struct msvc_tuple_get;
|
||||
|
||||
template<typename T>
|
||||
struct msvc_tuple_get<true, T> {
|
||||
template<class Tuple>
|
||||
static decltype(auto) fn(const Tuple& t) {
|
||||
return std::get<T>(t);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct msvc_tuple_get<false, T> {
|
||||
template<class Tuple>
|
||||
static decltype(auto) fn(const Tuple&) {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
#endif
|
||||
|
||||
template<class... Policies>
|
||||
template<class... Options>
|
||||
registry<Policies...>::compiler<Options...>::compiler(Options... opts)
|
||||
: opts(opts...), trace(detail::option<openmethod::trace>(this->opts).on),
|
||||
tr(trace) {
|
||||
: options(opts...) {
|
||||
if constexpr (has_trace) {
|
||||
#ifdef _MSC_VER
|
||||
tr.on = detail::msvc_tuple_get<has_trace, trace>::fn(options).on;
|
||||
#else
|
||||
// Even with the constexpr has_trace guard, msvc errors on this.
|
||||
tr.on = std::get<trace>(options).on;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template<class... Policies>
|
||||
@@ -1148,7 +1188,7 @@ void registry<Policies...>::compiler<Options...>::build_dispatch_table(
|
||||
m.dispatch_table.push_back(&m.not_implemented);
|
||||
++m.report.not_implemented;
|
||||
} else {
|
||||
if constexpr (!use_n2216) {
|
||||
if constexpr (!has_option<n2216>) {
|
||||
if (remaining > 1) {
|
||||
++tr << "ambiguous\n";
|
||||
m.dispatch_table.push_back(&m.ambiguous);
|
||||
@@ -1209,7 +1249,7 @@ void registry<Policies...>::compiler<Options...>::build_dispatch_table(
|
||||
|
||||
select_dominant_overriders(overriders, pick, remaining);
|
||||
|
||||
if constexpr (!use_n2216) {
|
||||
if constexpr (!has_option<n2216>) {
|
||||
if (remaining > 1) {
|
||||
++tr << "ambiguous 'next'\n";
|
||||
overrider->next = &m.ambiguous;
|
||||
@@ -1368,7 +1408,7 @@ void registry<Policies...>::compiler<Options...>::write_global_data() {
|
||||
++tr << rflush(4, dispatch_data_size) << " " << gv_iter << " end\n";
|
||||
|
||||
if constexpr (has_vptr) {
|
||||
vptr::initialize(classes.begin(), classes.end(), opts);
|
||||
vptr::initialize(*this, options);
|
||||
}
|
||||
|
||||
new_dispatch_data.swap(dispatch_data);
|
||||
@@ -1407,7 +1447,7 @@ void registry<Policies...>::compiler<Options...>::select_dominant_overriders(
|
||||
return;
|
||||
}
|
||||
|
||||
if constexpr (use_n2216) {
|
||||
if constexpr (has_option<n2216>) {
|
||||
if (!candidates[pick]->covariant_return_type) {
|
||||
return;
|
||||
}
|
||||
@@ -1571,10 +1611,6 @@ void registry<Policies...>::compiler<Options...>::print(
|
||||
//! @endcode
|
||||
template<class Registry = BOOST_OPENMETHOD_DEFAULT_REGISTRY, class... Options>
|
||||
inline auto initialize(Options&&... options) {
|
||||
static_assert(
|
||||
(std::is_base_of_v<detail::option_base, Options> && ...),
|
||||
"invalid option type");
|
||||
|
||||
if (detail::odr_check<Registry>::count > 1) {
|
||||
// Multiple definitions of default_registry detected.
|
||||
// This indicates an ODR violation.
|
||||
|
||||
@@ -80,10 +80,10 @@ struct fast_perfect_hash : type_hash {
|
||||
|
||||
static void check(std::size_t index, type_id type);
|
||||
|
||||
template<class ForwardIterator, class... Options>
|
||||
template<class InitializeContext, class... Options>
|
||||
static void initialize(
|
||||
ForwardIterator first, ForwardIterator last,
|
||||
std::vector<type_id>& buckets, std::tuple<Options...> options);
|
||||
const InitializeContext& ctx, std::vector<type_id>& buckets,
|
||||
const std::tuple<Options...>& options);
|
||||
|
||||
public:
|
||||
//! Find the hash factors
|
||||
@@ -95,25 +95,18 @@ struct fast_perfect_hash : type_hash {
|
||||
//! If no suitable values are found, calls the error handler with
|
||||
//! a @ref hash_error object then calls `abort`.
|
||||
//!
|
||||
//! @tparam ForwardIterator An iterator to a range of @ref
|
||||
//! IdsToVptr objects.
|
||||
//! @tparam Options... Zero or more option types, deduced from the
|
||||
//! function arguments.
|
||||
//! @param first An iterator to the beginning of the range.
|
||||
//! @param last An iterator to the end of the range.
|
||||
//! @param options Zero or more option objects.
|
||||
//! @tparam Context An @ref InitializeContext.
|
||||
//! @param ctx A Context object.
|
||||
//! @return A pair containing the minimum and maximum hash values.
|
||||
template<class ForwardIterator, class... Options>
|
||||
static auto initialize(
|
||||
ForwardIterator first, ForwardIterator last,
|
||||
std::tuple<Options...> options) {
|
||||
template<class Context, class... Options>
|
||||
static auto
|
||||
initialize(const Context& ctx, const std::tuple<Options...>& options) {
|
||||
if constexpr (Registry::has_runtime_checks) {
|
||||
initialize(
|
||||
first, last, detail::fast_perfect_hash_control<Registry>,
|
||||
options);
|
||||
ctx, detail::fast_perfect_hash_control<Registry>, options);
|
||||
} else {
|
||||
std::vector<type_id> buckets;
|
||||
initialize(first, last, buckets, options);
|
||||
initialize(ctx, buckets, options);
|
||||
}
|
||||
|
||||
return std::pair{min_value, max_value};
|
||||
@@ -150,7 +143,7 @@ struct fast_perfect_hash : type_hash {
|
||||
//! arguments.
|
||||
//! @param options Zero or more option objects.
|
||||
template<class... Options>
|
||||
static auto finalize(std::tuple<Options...>) -> void {
|
||||
static auto finalize(const std::tuple<Options...>&) -> void {
|
||||
detail::fast_perfect_hash_control<Registry>.clear();
|
||||
}
|
||||
};
|
||||
@@ -169,21 +162,16 @@ template<class Registry>
|
||||
std::size_t fast_perfect_hash::fn<Registry>::max_value;
|
||||
|
||||
template<class Registry>
|
||||
template<class ForwardIterator, class... Options>
|
||||
template<class InitializeContext, class... Options>
|
||||
void fast_perfect_hash::fn<Registry>::initialize(
|
||||
ForwardIterator first, ForwardIterator last, std::vector<type_id>& buckets,
|
||||
std::tuple<Options...> opts) {
|
||||
using namespace policies;
|
||||
const InitializeContext& ctx, std::vector<type_id>& buckets,
|
||||
const std::tuple<Options...>& options) {
|
||||
(void)options;
|
||||
|
||||
const auto N = std::distance(first, last);
|
||||
(void)opts;
|
||||
const auto N = std::distance(ctx.classes_begin(), ctx.classes_end());
|
||||
|
||||
if constexpr (
|
||||
detail::has_option<trace, Options...> && Registry::has_output) {
|
||||
if (detail::option<trace>(opts).on) {
|
||||
Registry::output::os << "Finding hash factor for " << N
|
||||
<< " types\n";
|
||||
}
|
||||
if constexpr (mp11::mp_contains<mp11::mp_list<Options...>, trace>::value) {
|
||||
Registry::output::os << "Finding hash factor for " << N << " types\n";
|
||||
}
|
||||
|
||||
std::default_random_engine rnd(13081963);
|
||||
@@ -202,13 +190,9 @@ void fast_perfect_hash::fn<Registry>::initialize(
|
||||
min_value = (std::numeric_limits<std::size_t>::max)();
|
||||
max_value = (std::numeric_limits<std::size_t>::min)();
|
||||
|
||||
if constexpr (
|
||||
mp11::mp_contains<mp11::mp_list<Options...>, trace>::value &&
|
||||
Registry::has_output) {
|
||||
if (detail::option<trace>(opts).on) {
|
||||
Registry::output::os << " trying with M = " << M << ", "
|
||||
<< hash_size << " buckets\n";
|
||||
}
|
||||
if constexpr (InitializeContext::template has_option<trace>) {
|
||||
ctx.tr << " trying with M = " << M << ", " << hash_size
|
||||
<< " buckets\n";
|
||||
}
|
||||
|
||||
std::size_t attempts = 0;
|
||||
@@ -221,7 +205,8 @@ void fast_perfect_hash::fn<Registry>::initialize(
|
||||
++total_attempts;
|
||||
mult = uniform_dist(rnd) | 1;
|
||||
|
||||
for (auto iter = first; iter != last; ++iter) {
|
||||
for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
|
||||
++iter) {
|
||||
for (auto type_iter = iter->type_id_begin();
|
||||
type_iter != iter->type_id_end(); ++type_iter) {
|
||||
auto type = *type_iter;
|
||||
@@ -238,15 +223,10 @@ void fast_perfect_hash::fn<Registry>::initialize(
|
||||
}
|
||||
}
|
||||
|
||||
if constexpr (
|
||||
mp11::mp_contains<mp11::mp_list<Options...>, trace>::value &&
|
||||
Registry::has_output) {
|
||||
if (detail::option<trace>(opts).on) {
|
||||
Registry::output::os
|
||||
<< " found " << mult << " after " << total_attempts
|
||||
<< " attempts; span = [" << min_value << ", "
|
||||
<< max_value << "]\n";
|
||||
}
|
||||
if constexpr (InitializeContext::template has_option<trace>) {
|
||||
ctx.tr << " found " << mult << " after " << total_attempts
|
||||
<< " attempts; span = [" << min_value << ", "
|
||||
<< max_value << "]\n";
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
@@ -38,20 +38,17 @@ class vptr_map : public vptr {
|
||||
public:
|
||||
//! Stores the v-table pointers.
|
||||
//!
|
||||
//! @tparam ForwardIterator An iterator to a range of @ref
|
||||
//! IdsToVptr objects.
|
||||
//! @tparam Options... Zero or more option types, deduced from the
|
||||
//! function arguments.
|
||||
//! @param first An iterator to the beginning of the range.
|
||||
//! @param last An iterator to the end of the range.
|
||||
//! @param options Zero or more option objects.
|
||||
template<class ForwardIterator, class... Options>
|
||||
static void initialize(
|
||||
ForwardIterator first, ForwardIterator last,
|
||||
std::tuple<Options...>) {
|
||||
//! @tparam Context An @ref InitializeContext.
|
||||
//! @tparam Options... Zero or more option types.
|
||||
//! @param ctx A Context object.
|
||||
//! @param options A tuple of option objects.
|
||||
template<class Context, class... Options>
|
||||
static void
|
||||
initialize(const Context& ctx, const std::tuple<Options...>&) {
|
||||
decltype(vptrs) new_vptrs;
|
||||
|
||||
for (auto iter = first; iter != last; ++iter) {
|
||||
for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
|
||||
++iter) {
|
||||
for (auto type_iter = iter->type_id_begin();
|
||||
type_iter != iter->type_id_end(); ++type_iter) {
|
||||
|
||||
@@ -109,11 +106,11 @@ class vptr_map : public vptr {
|
||||
|
||||
//! Clears the map.
|
||||
//!
|
||||
//! @tparam Options... Zero or more option types, deduced from the
|
||||
//! function arguments.
|
||||
//! @param options Zero or more option objects.
|
||||
//! @tparam Options... Zero or more option types.
|
||||
//! @param ctx A Context object.
|
||||
//! @param options A tuple of option objects.
|
||||
template<class... Options>
|
||||
static auto finalize(std::tuple<Options...>) -> void {
|
||||
static auto finalize(const std::tuple<Options...>&) -> void {
|
||||
vptrs.clear();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,29 +58,24 @@ struct vptr_vector : vptr {
|
||||
//! function is called. Its result determines the size of the vector.
|
||||
//! The v-table pointers are copied into the vector.
|
||||
//!
|
||||
//! @tparam ForwardIterator An iterator to a range of @ref
|
||||
//! IdsToVptr objects.
|
||||
//! @tparam Options... Zero or more option types, deduced from the
|
||||
//! function arguments.
|
||||
//! @param first An iterator to the beginning of the range.
|
||||
//! @param last An iterator to the end of the range.
|
||||
//! @param options Zero or more option objects.
|
||||
template<class ForwardIterator, class... Options>
|
||||
//! @tparam Context An @ref InitializeContext.
|
||||
//! @tparam Options... Zero or more option types.
|
||||
//! @param ctx A Context object.
|
||||
//! @param options A tuple of option objects.
|
||||
template<class Context, class... Options>
|
||||
static auto initialize(
|
||||
ForwardIterator first, ForwardIterator last,
|
||||
std::tuple<Options...> opts) -> void {
|
||||
(void)opts;
|
||||
const Context& ctx, const std::tuple<Options...>& options) -> void {
|
||||
std::size_t size;
|
||||
(void)options;
|
||||
|
||||
if constexpr (has_type_hash) {
|
||||
auto [_, max_value] =
|
||||
type_hash::template initialize<ForwardIterator, Options...>(
|
||||
first, last, opts);
|
||||
auto [_, max_value] = type_hash::initialize(ctx, options);
|
||||
size = max_value + 1;
|
||||
} else {
|
||||
size = 0;
|
||||
|
||||
for (auto iter = first; iter != last; ++iter) {
|
||||
for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
|
||||
++iter) {
|
||||
for (auto type_iter = iter->type_id_begin();
|
||||
type_iter != iter->type_id_end(); ++type_iter) {
|
||||
size = (std::max)(size, std::size_t(*type_iter));
|
||||
@@ -96,7 +91,8 @@ struct vptr_vector : vptr {
|
||||
detail::vptr_vector_vptrs<Registry>.resize(size);
|
||||
}
|
||||
|
||||
for (auto iter = first; iter != last; ++iter) {
|
||||
for (auto iter = ctx.classes_begin(); iter != ctx.classes_end();
|
||||
++iter) {
|
||||
for (auto type_iter = iter->type_id_begin();
|
||||
type_iter != iter->type_id_end(); ++type_iter) {
|
||||
std::size_t index;
|
||||
@@ -173,13 +169,13 @@ struct vptr_vector : vptr {
|
||||
}
|
||||
}
|
||||
|
||||
//! Clears the vector.
|
||||
//! Releases the memory allocated by `initialize`.
|
||||
//!
|
||||
//! @tparam Options... Zero or more option types, deduced from the
|
||||
//! function arguments.
|
||||
//! @tparam Options... Zero or more option types, deduced from the function
|
||||
//! arguments.
|
||||
//! @param options Zero or more option objects.
|
||||
template<class... Options>
|
||||
static auto finalize(std::tuple<Options...>) -> void {
|
||||
static auto finalize(const std::tuple<Options...>&) -> void {
|
||||
using namespace policies;
|
||||
|
||||
if constexpr (Registry::has_indirect_vptr) {
|
||||
|
||||
@@ -368,6 +368,8 @@ struct deferred_overrider_info : overrider_info {
|
||||
virtual void resolve_type_ids() = 0;
|
||||
};
|
||||
|
||||
struct unspecified {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
#ifdef __MRDOCS__
|
||||
@@ -385,28 +387,6 @@ struct LightweightOutputStream {
|
||||
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<class Target, class... Options>
|
||||
constexpr bool has_option =
|
||||
mp11::mp_contains<mp11::mp_list<Options...>, Target>::value;
|
||||
|
||||
template<class Target, class... Options>
|
||||
inline auto option(std::tuple<Options...> opts) {
|
||||
constexpr auto index =
|
||||
mp11::mp_find<mp11::mp_list<Options...>, Target>::value;
|
||||
|
||||
if constexpr (index == sizeof...(Options)) {
|
||||
return Target();
|
||||
} else {
|
||||
return std::get<index>(opts);
|
||||
}
|
||||
}
|
||||
|
||||
struct option_base {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
//! N2216 ambiguity resolution.
|
||||
//!
|
||||
//! If `n2216` is present in @ref initialize\'s `Options`, additional steps are
|
||||
@@ -422,7 +402,7 @@ struct option_base {};
|
||||
//! - Otherwise, pick one of the overriders. Which one is used is unspecified,
|
||||
//! but remains the same throughtout the program, and across different runs of
|
||||
//! the same program.
|
||||
struct n2216 : detail::option_base {};
|
||||
struct n2216 {};
|
||||
|
||||
//! Enable `initialize` tracing.
|
||||
//!
|
||||
@@ -437,7 +417,7 @@ struct n2216 : detail::option_base {};
|
||||
//! The content of the trace is neither specified, nor stable across versions.
|
||||
//! It is comprehensive, and useful for troubleshooting missing class
|
||||
//! registrations, missing or ambiguous overriders, etc.
|
||||
struct trace : detail::option_base {
|
||||
struct trace {
|
||||
//! Enable trace if `true`.
|
||||
bool on = true;
|
||||
|
||||
@@ -477,23 +457,48 @@ namespace policies {
|
||||
|
||||
#ifdef __MRDOCS__
|
||||
|
||||
//! Type ids and v-table pointers for a class (exposition only).
|
||||
struct IdsToVptr {
|
||||
//! Returns an iterator to the beginning of a range of `type_id`s for a
|
||||
//! single registered class.
|
||||
auto type_id_begin() const;
|
||||
//! Class information for initializing a policy (exposition only).
|
||||
//!
|
||||
//! Provides the v-table pointer for a class, identified by one or more type
|
||||
//! ids, via the members described on this page.
|
||||
struct InitializeClass {
|
||||
//! Beginning of a range of type ids for a class.
|
||||
//!
|
||||
//! @return A forward iterator to the beginning of a range of type ids for
|
||||
//! a class.
|
||||
auto type_id_begin() const -> detail::unspecified;
|
||||
|
||||
//! Returns an iterator to the end of a range of `type_id`s for a
|
||||
//! single registered class.
|
||||
auto type_id_end() const;
|
||||
//! End of a range of type ids for a class.
|
||||
//!
|
||||
//! @return A forward iterator to the end of a range of type ids for a
|
||||
//! class.
|
||||
auto type_id_end() const -> detail::unspecified;
|
||||
|
||||
//! Returns a range of `type_id`s that this assignment applies to.
|
||||
//! Reference to the v-table pointer for the class.
|
||||
//!
|
||||
//! @return A reference to the v-table pointer for the class.
|
||||
auto vptr() const -> const vptr_type&;
|
||||
};
|
||||
|
||||
#endif
|
||||
//! Context for initializing a policy (exposition only).
|
||||
//!
|
||||
//! @ref initialize passes a "context" object, of unspecified type, to the
|
||||
//! `initialize` functions of the policies that have one. It provides the
|
||||
//! v-table pointer for the registered classes, via the members described on
|
||||
//! this page.
|
||||
struct InitializeContext {
|
||||
//! Beginning of a range of `InitializeClass` objects.
|
||||
//!
|
||||
//! @return A forward iterator to the beginning of a range of @ref
|
||||
//! InitializeClass objects.
|
||||
detail::unspecified classes_begin() const;
|
||||
|
||||
#ifdef __MRDOCS__
|
||||
//! End of a range of `InitializeClass` objects.
|
||||
//!
|
||||
//! @return A forward iterator to the end of a range of @ref
|
||||
//! InitializeClass objects.
|
||||
detail::unspecified classes_end() const;
|
||||
};
|
||||
|
||||
//! Blueprint for @ref rtti metafunctions (exposition only).
|
||||
template<class Registry>
|
||||
@@ -588,11 +593,6 @@ struct rtti {
|
||||
};
|
||||
};
|
||||
|
||||
#ifdef __MRDOCS__
|
||||
struct std_rtti;
|
||||
struct static_rtti;
|
||||
#endif
|
||||
|
||||
//! Policy for deferred type id collection.
|
||||
//!
|
||||
//! Some custom RTTI systems rely on static constructors to assign type ids.
|
||||
@@ -643,17 +643,10 @@ struct VptrFn {
|
||||
//! Called by @ref registry::initialize to let the policy store the v-table
|
||||
//! pointer associated to each `type_id`.
|
||||
//!
|
||||
//! @tparam ForwardIterator An iterator to a range of @ref
|
||||
//! IdsToVptr objects.
|
||||
//! @tparam Options... Zero or more option types, deduced from the
|
||||
//! function arguments.
|
||||
//! @param first An iterator to the beginning of the range.
|
||||
//! @param last An iterator to the end of the range.
|
||||
//! @param options Zero or more option objects.
|
||||
template<typename ForwardIterator, class... Options>
|
||||
static auto initialize(
|
||||
ForwardIterator first, ForwardIterator last,
|
||||
std::tuple<Options...> opts);
|
||||
//! @tparam Context A class that conforms to the @ref InitializeContext
|
||||
//! blueprint.
|
||||
template<class Context>
|
||||
static auto initialize(const Context& ctx) -> void;
|
||||
|
||||
//! Return a *reference* to a v-table pointer for an object.
|
||||
//!
|
||||
@@ -712,7 +705,7 @@ struct TypeHashFn {
|
||||
//! Initialize the hash table.
|
||||
//!
|
||||
//! @tparam ForwardIterator An iterator to a range of @ref
|
||||
//! IdsToVptr objects.
|
||||
//! InitializeClass objects.
|
||||
//! @tparam Options... Zero or more option types, deduced from the
|
||||
//! function arguments.
|
||||
//! @param first An iterator to the beginning of the range.
|
||||
|
||||
@@ -294,7 +294,7 @@ BOOST_AUTO_TEST_CASE(cast_shared_ptr_lvalue_reference) {
|
||||
|
||||
bool cast_moves() {
|
||||
std::shared_ptr<Animal> animal = std::make_shared<Dog>();
|
||||
(void) std::static_pointer_cast<Dog>(animal);
|
||||
(void)std::static_pointer_cast<Dog>(animal);
|
||||
|
||||
return animal.get() == nullptr;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user