Skip to content

Commit 4c3839a

Browse files
committed
wip
1 parent f970a16 commit 4c3839a

File tree

5 files changed

+114
-62
lines changed

5 files changed

+114
-62
lines changed

doc/rtti.adoc

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,23 @@ an `ostream`-like object.
2424
#### is_polymorphic
2525

2626
```c++
27-
template<class Class>
28-
static constexpr bool is_polymorphic;
27+
template<class Class> static constexpr bool is_polymorphic;
2928
```
3029

3130
`true` if `Class` is polymorphic.
3231

3332
#### static_type
3433

3534
```c++
36-
template<class Class>
37-
static auto static_type() -> type_id;
35+
template<class Class> static auto static_type() -> type_id;
3836
```
3937

4038
Returns a `type_id` for `Class`.
4139

4240
#### dynamic_type
4341

4442
```c++
45-
template<class Class>
46-
static auto dynamic_type(const Class& obj) -> type_id;
43+
template<class Class> static auto dynamic_type(const Class& obj) -> type_id;
4744
```
4845

4946
Returns a `type_id` for an object's dynamic type.

include/boost/openmethod/policies/fast_perfect_hash.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ struct fast_perfect_hash : type_hash {
6060
initialize(first, last, buckets);
6161
}
6262

63-
return report{hash_min, hash_max};
63+
return std::pair{hash_min, hash_max};
6464
}
6565

6666
template<typename ForwardIterator>

include/boost/openmethod/policies/vptr_vector.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,9 @@ struct vptr_vector : extern_vptr {
3535
std::size_t size;
3636

3737
if constexpr (Registry::template has_policy<type_hash>) {
38-
auto report = Registry::template policy<type_hash>::initialize(
38+
auto [_, max_value] = Registry::template policy<type_hash>::initialize(
3939
first, last);
40-
size = report.last + 1;
40+
size = max_value + 1;
4141
} else {
4242
size = 0;
4343

include/boost/openmethod/registry.hpp

Lines changed: 106 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -11,72 +11,127 @@
1111

1212
namespace boost::openmethod {
1313

14-
namespace policies {
15-
16-
/**
17-
Base class for all policies.
18-
19-
A @e policy is a direct subclass of `policy`. Each such subclass
20-
21-
A @ref
22-
23-
@par Requirements
24-
25-
A policy must provide a typedef that identifies its category, which must be
26-
a direct derived class of `policy`. The category identifies the policy in
27-
the registry.
28-
29-
@code
30-
using category = <policy direct derived class>;
31-
@endcode
32-
33-
<policy_category> must be one of the following:
14+
//! Namespace containing the policy framework.
15+
//!
16+
//! A @e policy is a class that controls how some fundamental operations are
17+
//! performed by the library: type information acquisition (`rtti`), v-table
18+
//! pointer acquisition (`vptr`), error handling (`error_handler`), etc.
19+
//!
20+
//! Some policies can be used directly in a registry's policy list. They
21+
//! function like flags, enabling blocks of code in the dispatch mechanism. For
22+
//! example, `runtime_checks` enables code that detects missing class
23+
//! registrations.
24+
//!
25+
//! Others policy classes need to be derived from. The subclass is required to
26+
//! contain a `template<class Registry> struct fn`, which contains a set static
27+
//! members that follow the requirements of the policy. For example, subclasses
28+
//! of `vptr` must provide a `fn` that contains a `static vptr_type
29+
//! dynamic_vptr(const Class& arg)` that returns a v-table pointer for an object
30+
//! of type `Class`.
3431

35-
- `rtti` obtain static type information for a class, and dynamic type
36-
information for an object.
37-
38-
- `error_handler`
39-
40-
- `type_hash`
41-
42-
- `vptr`
43-
44-
- `indirect_vptr`
45-
46-
- `output`
47-
48-
- `trace`
49-
50-
- `runtime_checks`
51-
52-
- `n2216`
53-
*/
54-
55-
struct policy {};
32+
namespace policies {
5633

57-
struct rtti : policy {
34+
//! RTTI policy base class.
35+
//!
36+
//! A @e rtti policy is responsible for acquiring and manipulating type
37+
//! information, dynamic casting, and identifying polymorphic classes.
38+
//!
39+
//! Class `rtti` provides a default implementation for some of these operations.
40+
//!
41+
//! @par Requirements
42+
//!
43+
//! A @e rtti policy must derive from class `rtti`, and contain a `fn<Registry>`
44+
//! class template with the following public static members:
45+
//!
46+
//! - `template<class Class> constexpr bool is_polymorphic`: evaluates to `true`
47+
//! if `Class` is polymorphic.
48+
//!
49+
//! - `template<class Class> type_id static_type()`: returns a `type_id`
50+
//! for `Class`.
51+
//!
52+
//! - `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`.
57+
//!
58+
//! - `template<typename Stream> void type_name(type_id type, Stream&
59+
//! stream)`: writes a description of `type` to `stream`.
60+
//!
61+
//! - `/* unspecified */ type_index(type_id type)`: returns a @e unique
62+
//! identifier for `type`.
63+
64+
struct rtti {
5865
using category = rtti;
5966

6067
template<class Register>
6168
struct fn {
69+
//! Default implementation of `type_index`.
70+
//!
71+
//! Returns `type`.
72+
//!
73+
//! @param type A `type_id`.
6274
static auto type_index(type_id type) -> type_id {
6375
return type;
6476
}
6577

78+
//! Default implementation of `type_name`.
79+
//!
80+
//! Executes `stream << "type_id(" << type << ")"`.
81+
//!
82+
//! @param type A `type_id`.
83+
//! @param stream A stream to write to.
6684
template<typename Stream>
6785
static void type_name(type_id type, Stream& stream) {
6886
stream << "type_id(" << type << ")";
6987
}
7088
};
7189
};
7290

91+
//! RTTI policy base class with defered type id collection.
92+
//!
93+
//! Some custom RTTI systems rely on static constructors to assign type ids.
94+
//! OpenMethod itself relies on static constructors to register classes, methods
95+
//! and overriders. This creates order-of-initialization issues. Deriving a @e
96+
//! rtti policy from this class - instead of just `rtti` - causes the collection
97+
//! of type ids to be deferred until the first call to @ref update.
7398
struct deferred_static_rtti : rtti {};
7499

75-
struct error_handler : policy {
100+
//! Error handling policy base class.
101+
//!
102+
//! A @e error_handler policy runs code before terminating the program due to an
103+
//! error. This can be useful for throwing, logging, cleanup, or other actions.
104+
//!
105+
//! @par Requirements
106+
//!
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`.
110+
111+
struct error_handler {
76112
using category = error_handler;
77113
};
78114

79-
struct type_hash : policy {
115+
//! Hashing policy base class.
116+
//!
117+
//! A @e type_hash policy calculates an integer hash for a `type_id`.
118+
//!
119+
//! @par Requirements
120+
//!
121+
//! A subclass of `error_handler` contains a `fn<Registry>` struct that provides
122+
//! the following static member functions:
123+
//! - auto initialize(ForwardIterator first, ForwardIterator last) -> [min,
124+
//! max]: initialize the hash table with the values in the [iter, last) range.
125+
//! `*iter` is an object of an unspecified type that has two members,
126+
//! `type_id_begin()` and `type_id_end()`, which return iterators to a range
127+
//! of `type_id`s. `initialize` returns a pair with the minimum and maximum
128+
//! hash values.
129+
//! - auto hash(type_id type) -> std::size_t: returns a hash value for `type`.
130+
//! The value must be in the range returned by `initialize`.
131+
//! - void finalize(): releases any resources allocated by `initialize`. This
132+
//! member is optional.
133+
134+
struct type_hash {
80135
using category = type_hash;
81136
};
82137

@@ -99,23 +154,23 @@ struct type_hash : policy {
99154
100155
*/
101156

102-
struct vptr : policy {
157+
struct vptr {
103158
using category = vptr;
104159
};
105160

106161
struct extern_vptr : vptr {};
107162

108-
struct indirect_vptr : policy {
163+
struct indirect_vptr {
109164
using category = indirect_vptr;
110165
template<class Registry>
111166
struct fn {};
112167
};
113168

114-
struct output : policy {
169+
struct output {
115170
using category = output;
116171
};
117172

118-
struct trace : policy {
173+
struct trace {
119174
using category = trace;
120175
template<class Registry>
121176
struct fn {
@@ -136,20 +191,20 @@ struct trace : policy {
136191
};
137192
};
138193

139-
struct runtime_checks : policy {
194+
struct runtime_checks {
140195
using category = runtime_checks;
141196
template<class Registry>
142197
struct fn {};
143198
};
144199

145-
struct n2216 : policy {
200+
struct n2216 {
146201
using category = n2216;
147202
template<class Registry>
148203
struct fn {};
149204
};
150205

151206
template<typename Key>
152-
struct unique : policy {
207+
struct unique {
153208
using category = unique;
154209
template<class Registry>
155210
struct fn {};

test/test_policies.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,14 +39,14 @@ static_assert(!detail::is_registry<not_a_policy>);
3939
struct registry1 : default_registry::with<unique<registry1>> {};
4040
struct registry2 : default_registry::with<unique<registry2>> {};
4141

42-
struct foo : policy {
42+
struct foo {
4343
using category = foo;
4444
};
4545

4646
struct foo1 : foo {};
4747
struct foo2 : foo {};
4848

49-
struct bar : policy {
49+
struct bar {
5050
using category = bar;
5151
};
5252

0 commit comments

Comments
 (0)