Skip to content

Commit a394ab7

Browse files
committed
wip
1 parent 4c3839a commit a394ab7

File tree

8 files changed

+122
-53
lines changed

8 files changed

+122
-53
lines changed

include/boost/openmethod/compiler.hpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1206,9 +1206,8 @@ void compiler<Registry>::write_global_data() {
12061206
++trace << rflush(4, Registry::dispatch_data.size()) << " " << gv_iter
12071207
<< " end\n";
12081208

1209-
if constexpr (Registry::template has_policy<extern_vptr>) {
1210-
Registry::template policy<extern_vptr>::register_vptrs(
1211-
classes.begin(), classes.end());
1209+
if constexpr (is_not_void<typename Registry::vptr>) {
1210+
Registry::vptr::register_vptrs(classes.begin(), classes.end());
12121211
}
12131212
}
12141213

include/boost/openmethod/default_registry.hpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,7 @@ struct release_registry
2222
policies::stderr_output> {};
2323

2424
struct debug_registry
25-
: registry<
26-
policies::std_rtti, policies::fast_perfect_hash,
27-
policies::vptr_vector, policies::default_error_handler,
28-
policies::runtime_checks, policies::stderr_output, policies::trace> {
29-
};
25+
: release_registry::with<policies::runtime_checks, policies::trace> {};
3026

3127
#ifdef NDEBUG
3228
using default_registry = release_registry;

include/boost/openmethod/policies/default_error_handler.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313

1414
namespace boost::openmethod::policies {
1515

16+
//! Calls a function via an indirection.
17+
1618
struct default_error_handler : error_handler {
1719
using error_variant = std::variant<
1820
not_initialized_error, not_implemented_error, ambiguous_error,

include/boost/openmethod/policies/std_rtti.hpp

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,41 +16,79 @@
1616

1717
namespace boost::openmethod::policies {
1818

19+
//! `rtti` policy using standard RTTI.
20+
//!
21+
//! This implementation of `rtti` uses the standard C++ RTTI system. It is the
22+
//! default RTTI policy.
23+
//!
24+
1925
struct std_rtti : rtti {
2026
#ifndef BOOST_NO_RTTI
21-
2227
template<class Registry>
2328
struct fn {
29+
//! Returns `true` if `Class` is polymorphic.
30+
//!
31+
//! A polymorphic class, as defined by the C++ standard, is a class that
32+
//! contains at least one virtual function.
33+
//!
34+
//! @tparam Class A class.
35+
2436
template<class Class>
2537
static constexpr bool is_polymorphic = std::is_polymorphic_v<Class>;
2638

39+
//! Returns the @ref type_id of `Class` is polymorphic.
40+
//!
41+
//! Returns the address of the `std::type_info` object for `Class`, cast
42+
//! to `type_id`.
43+
//!
44+
//! @note `Class` is not necessarily a @e registered class. This
45+
//! function is also called to acquire the type_id of non-virtual
46+
//! parameters, library types, etc, for diagnostic and trace purposes.
47+
//!
48+
//! @tparam Class A class.
49+
2750
template<class Class>
2851
static auto static_type() -> type_id {
2952
return &typeid(Class);
3053
}
3154

55+
//! Returns the @ref type_id of `obj`.
56+
//!
57+
//! Returns the address of the `std::type_info` object for `obj`, cast to `type_id`.
58+
3259
template<class Class>
3360
static auto dynamic_type(const Class& obj) -> type_id {
3461
return &typeid(obj);
3562
}
3663

64+
//! Writes the demangled name of the class identified by `type` to
65+
//! `stream`.
66+
3767
template<typename Stream>
3868
static auto type_name(type_id type, Stream& stream) -> void {
3969
stream << boost::core::demangle(
4070
reinterpret_cast<const std::type_info*>(type)->name());
4171
}
4272

73+
//! Returns the `std::type_index` of `type`.
74+
//!
75+
//! This function is required because C++ does *not* guarantee that
76+
//! there is a single instance of `std::type_info` per type.
77+
4378
static auto type_index(type_id type) -> std::type_index {
4479
return std::type_index(
4580
*reinterpret_cast<const std::type_info*>(type));
4681
}
4782

83+
//! Casts `obj` to type `D`.
84+
//!
85+
//! Casts `obj` to `D` using `dynamic_cast`.
86+
4887
template<typename D, typename B>
4988
static auto dynamic_cast_ref(B&& obj) -> D {
5089
return dynamic_cast<D>(obj);
5190
}
5291
};
53-
5492
#endif
5593
};
5694

include/boost/openmethod/policies/vptr_map.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace boost::openmethod {
1515
namespace policies {
1616

1717
template<class MapAdaptor = mp11::mp_quote<std::unordered_map>>
18-
class vptr_map : public extern_vptr {
18+
class vptr_map : public vptr {
1919
public:
2020
template<class Registry>
2121
struct fn {

include/boost/openmethod/policies/vptr_vector.hpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ inline std::vector<const vptr_type*> vptr_vector_indirect_vptrs;
2525

2626
namespace policies {
2727

28-
struct vptr_vector : extern_vptr {
28+
struct vptr_vector : vptr {
2929
public:
3030
template<class Registry>
3131
struct fn {
@@ -35,8 +35,9 @@ struct vptr_vector : extern_vptr {
3535
std::size_t size;
3636

3737
if constexpr (Registry::template has_policy<type_hash>) {
38-
auto [_, max_value] = Registry::template policy<type_hash>::initialize(
39-
first, last);
38+
auto [_, max_value] =
39+
Registry::template policy<type_hash>::initialize(
40+
first, last);
4041
size = max_value + 1;
4142
} else {
4243
size = 0;

include/boost/openmethod/registry.hpp

Lines changed: 70 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,33 @@ namespace boost::openmethod {
1313

1414
//! Namespace containing the policy framework.
1515
//!
16+
//! A registry contains a list of policies that control how some operations are
17+
//! performed. Policies fall into categories, depending on which subset of
18+
//! operations they control. Each category has a corresponding class:
19+
//!
20+
//! - @ref vptr: v-table pointer acquisition.
21+
//!
22+
//! - @ref rtti: type information acquisition and manipulation.
23+
//!
24+
//! - @ref type_hash: hashing of `type_id`s.
25+
//!
26+
//! - @ref error_handler: perform operations when errors are detected.
27+
//!
28+
//! - @ref output: output stream for logging and debugging.
29+
//!
30+
//! - @ref runtime_checks: detect and report common errors.
31+
//!
32+
//! - @ref trace: report how dispatch tables are built.
33+
//!
34+
//! - @ref n2216: handle ambiguities according to the N2216 proposal.
35+
//!
36+
//! The last three policy categories act like flags. They can appear in the
37+
//! registry's policy list, and enable existing blocks of code.
38+
//!
39+
//! The other categories cannot be used directly. They must be subclassed, and
40+
//! the subclass must contain a `template<class Registry> struct fn` that
41+
//! provides a set of static members that depends on the policy's category.
42+
//!
1643
//! A @e policy is a class that controls how some fundamental operations are
1744
//! performed by the library: type information acquisition (`rtti`), v-table
1845
//! pointer acquisition (`vptr`), error handling (`error_handler`), etc.
@@ -36,12 +63,10 @@ namespace policies {
3663
//! A @e rtti policy is responsible for acquiring and manipulating type
3764
//! information, dynamic casting, and identifying polymorphic classes.
3865
//!
39-
//! Class `rtti` provides a default implementation for some of these operations.
40-
//!
4166
//! @par Requirements
4267
//!
43-
//! A @e rtti policy must derive from class `rtti`, and contain a `fn<Registry>`
44-
//! class template with the following public static members:
68+
//! A subclass of `rtti` must contain a `fn<Registry>` class template with the
69+
//! following public static members:
4570
//!
4671
//! - `template<class Class> constexpr bool is_polymorphic`: evaluates to `true`
4772
//! if `Class` is polymorphic.
@@ -50,16 +75,21 @@ namespace policies {
5075
//! for `Class`.
5176
//!
5277
//! - `template<class Class> type_id dynamic_type(const Class& obj)`:
53-
//! returns the type_id of an object's dynamic type.
54-
//!
55-
//! - `template<typename Stream> void type_name(type_id type, Stream&
56-
//! stream)`: writes a description of `type` to `stream`.
78+
//! returns the type_id of the @e dynamic type of `obj`.
5779
//!
58-
//! - `template<typename Stream> void type_name(type_id type, Stream&
59-
//! stream)`: writes a description of `type` to `stream`.
80+
//! - `template<typename Stream> void type_name(type_id type, Stream& stream)`:
81+
//! writes a description of `type` to `stream`. `rtti::fn` provides a default
82+
//! implementation.
6083
//!
6184
//! - `/* unspecified */ type_index(type_id type)`: returns a @e unique
62-
//! identifier for `type`.
85+
//! identifier for `type`. `rtti::fn` provides a default implementation.
86+
//!
87+
//! The following functions is required only if casting from base to derived
88+
//! class cannot be performed using a `static_cast` for some of the registered
89+
//! classes:
90+
//!
91+
//! - `template<typename D, typename B> D dynamic_cast_ref(B&& obj)`: casts
92+
//! `obj` to reference type `D`.
6393

6494
struct rtti {
6595
using category = rtti;
@@ -88,7 +118,7 @@ struct rtti {
88118
};
89119
};
90120

91-
//! RTTI policy base class with defered type id collection.
121+
//! RTTI policy base class for defered type id collection.
92122
//!
93123
//! Some custom RTTI systems rely on static constructors to assign type ids.
94124
//! OpenMethod itself relies on static constructors to register classes, methods
@@ -104,9 +134,10 @@ struct deferred_static_rtti : rtti {};
104134
//!
105135
//! @par Requirements
106136
//!
107-
//! A subclass of `error_handler` contains a `fn<Registry>` struct that provides
108-
//! one or more `error` static functions that take an error object. `error` must
109-
//! be callable with an instance of any subclass of `openmethod_error`.
137+
//! A subclass of `error_handler` must contain a `fn<Registry>` struct that
138+
//! provides one or more `error` static functions that take an error object.
139+
//! `error` must be callable with an instance of any subclass of
140+
//! `openmethod_error`.
110141

111142
struct error_handler {
112143
using category = error_handler;
@@ -118,48 +149,50 @@ struct error_handler {
118149
//!
119150
//! @par Requirements
120151
//!
121-
//! A subclass of `error_handler` contains a `fn<Registry>` struct that provides
152+
//! A subclass of `type_hash` must contain a `fn<Registry>` struct that provides
122153
//! the following static member functions:
154+
//!
123155
//! - auto initialize(ForwardIterator first, ForwardIterator last) -> [min,
124156
//! max]: initialize the hash table with the values in the [iter, last) range.
125157
//! `*iter` is an object of an unspecified type that has two members,
126158
//! `type_id_begin()` and `type_id_end()`, which return iterators to a range
127159
//! of `type_id`s. `initialize` returns a pair with the minimum and maximum
128160
//! hash values.
161+
//!
129162
//! - auto hash(type_id type) -> std::size_t: returns a hash value for `type`.
130163
//! The value must be in the range returned by `initialize`.
164+
//!
131165
//! - void finalize(): releases any resources allocated by `initialize`. This
132166
//! member is optional.
133167

134168
struct type_hash {
135169
using category = type_hash;
136170
};
137171

138-
/**
139-
Acquires a v-table pointer for an object.
140-
141-
@par Requirements
142-
143-
Any implementation of this policy must provide a meta-function `fn` that
144-
in the form of:
145-
146-
@code
147-
template<class Registry>
148-
struct fn {
149-
template<class Class> static auto dynamic_vptr(const Class& arg) -> const vptr_type&;
150-
};
151-
@endcode
152-
153-
@see policies::vptr_vector::fn::dynamic_vptr for an example.
154-
155-
*/
172+
//! Acquires a v-table pointer for an object.
173+
//!
174+
//! @par Requirements
175+
//!
176+
//! A subclass of `type_hash` must contain a `fn<Registry>` struct that provides
177+
//! the following static member functions:
178+
//!
179+
//! - auto initialize(ForwardIterator first, ForwardIterator last) -> [min,
180+
//! max]: initialize the hash table with the values in the [iter, last) range.
181+
//! `*iter` is an object of an unspecified type that has two members,
182+
//! `type_id_begin()` and `type_id_end()`, which return iterators to a range
183+
//! of `type_id`s. `initialize` returns a pair with the minimum and maximum
184+
//! hash values.
185+
//!
186+
//! - auto hash(type_id type) -> std::size_t: returns a hash value for `type`.
187+
//! The value must be in the range returned by `initialize`.
188+
//!
189+
//! - void finalize(): releases any resources allocated by `initialize`. This
190+
//! member is optional.
156191

157192
struct vptr {
158193
using category = vptr;
159194
};
160195

161-
struct extern_vptr : vptr {};
162-
163196
struct indirect_vptr {
164197
using category = indirect_vptr;
165198
template<class Registry>
@@ -324,6 +357,7 @@ struct registry : detail::registry_base {
324357
static constexpr auto indirect_vptr = has_policy<policies::indirect_vptr>;
325358

326359
using rtti = policy<policies::rtti>;
360+
using vptr = policy<policies::vptr>;
327361
using error_handler = policy<policies::error_handler>;
328362
using output = policy<policies::output>;
329363
using trace = policy<policies::trace>;

test/test_intrusive.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@
99
#include <boost/openmethod/default_registry.hpp>
1010

1111
namespace bom = boost::openmethod;
12-
struct test_registry
13-
: bom::default_registry::without<
14-
bom::policies::extern_vptr, bom::policies::type_hash> {};
12+
struct test_registry : bom::default_registry::without<
13+
bom::policies::vptr, bom::policies::type_hash> {};
1514

1615
#define BOOST_OPENMETHOD_DEFAULT_REGISTRY test_registry
1716

0 commit comments

Comments
 (0)