Skip to content

Commit 16b7514

Browse files
committed
more doc
1 parent 044cf31 commit 16b7514

File tree

9 files changed

+293
-285
lines changed

9 files changed

+293
-285
lines changed

doc/modules/ROOT/examples/ast.cpp

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -5,80 +5,65 @@
55

66
// clang-format off
77

8-
// tag::ast[]
9-
10-
#include <iostream>
11-
12-
#include <boost/openmethod.hpp>
13-
#include <boost/openmethod/initialize.hpp>
14-
15-
using boost::openmethod::virtual_ptr;
16-
8+
// tag::content[]
179
struct Node {
1810
virtual ~Node() {}
11+
virtual int value() const = 0;
1912
};
2013

2114
struct Variable : Node {
22-
explicit Variable(int value) : value(value) {}
23-
24-
int value;
15+
Variable(int value) : v(value) {}
16+
int value() const override { return v; }
17+
int v;
2518
};
2619

2720
struct Plus : Node {
28-
Plus(virtual_ptr<Node> left, virtual_ptr<Node> right)
29-
: left(left), right(right) {}
30-
31-
virtual_ptr<Node> left, right;
21+
Plus(const Node& left, const Node& right) : left(left), right(right) {}
22+
int value() const override { return left.value() + right.value(); }
23+
const Node& left; const Node& right;
3224
};
3325

34-
struct Negate : Node {
35-
explicit Negate(virtual_ptr<Node> node) : child(node) {}
36-
37-
virtual_ptr<Node> child;
26+
struct Times : Node {
27+
Times(const Node& left, const Node& right) : left(left), right(right) {}
28+
int value() const override { return left.value() * right.value(); }
29+
const Node& left; const Node& right;
3830
};
3931

40-
BOOST_OPENMETHOD(value, (virtual_ptr<Node>), int);
32+
#include <boost/openmethod.hpp>
33+
#include <boost/openmethod/initialize.hpp>
34+
#include <iostream>
4135

42-
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Variable> node), int) {
43-
return node->value;
44-
}
36+
using boost::openmethod::virtual_ptr;
4537

46-
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Plus> node), int) {
47-
return value(node->left) + value(node->right);
48-
}
38+
BOOST_OPENMETHOD(postfix, (virtual_ptr<const Node> node, std::ostream& os), void);
4939

50-
BOOST_OPENMETHOD_OVERRIDE(value, (virtual_ptr<Negate> node), int) {
51-
return -value(node->child);
40+
BOOST_OPENMETHOD_OVERRIDE(
41+
postfix, (virtual_ptr<const Variable> var, std::ostream& os), void) {
42+
os << var->v;
5243
}
5344

54-
BOOST_OPENMETHOD_CLASSES(Node, Variable, Plus, Negate);
55-
56-
auto main() -> int {
57-
boost::openmethod::initialize();
58-
59-
Variable one(1), two(2);
60-
Plus sum(one, two);
61-
Negate neg(sum);
62-
63-
std::cout << value(neg) << "\n"; // -3
64-
65-
return 0;
45+
BOOST_OPENMETHOD_OVERRIDE(
46+
postfix, (virtual_ptr<const Plus> plus, std::ostream& os), void) {
47+
postfix(plus->left, os);
48+
os << ' ';
49+
postfix(plus->right, os);
50+
os << " +";
6651
}
67-
// end::ast[]
6852

69-
auto negate(virtual_ptr<Node> node) -> int {
70-
return -value(node);
53+
BOOST_OPENMETHOD_OVERRIDE(
54+
postfix, (virtual_ptr<const Times> times, std::ostream& os), void) {
55+
postfix(times->left, os);
56+
os << ' ';
57+
postfix(times->right, os);
58+
os << " *";
7159
}
7260

73-
#define main alt_main
61+
BOOST_OPENMETHOD_CLASSES(Node, Variable, Plus, Times);
7462

75-
auto main() -> int {
76-
// tag::final[]
77-
Variable one(1);
78-
Negate neg(boost::openmethod::final_virtual_ptr(one));
79-
// end::final[]
80-
81-
std::cout << value(boost::openmethod::final_virtual_ptr(neg)) << "\n"; // -3
82-
83-
return 0;
63+
int main() {
64+
boost::openmethod::initialize();
65+
Variable a{2}, b{3}, c{4};
66+
Plus d{a, b}; Times e{d, c};
67+
postfix(e, std::cout);
68+
std::cout << " = " << e.value() << "\n"; // 2 3 + 4 * = 20
8469
}

doc/modules/ROOT/examples/ast_virtual_function.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55

66
// clang-format off
77

8+
// tag::content[]
89
#include <iostream>
910

10-
// tag::all[]
11-
1211
struct Node {
1312
virtual ~Node() {}
1413
virtual int value() const = 0;
@@ -35,6 +34,6 @@ struct Times : Node {
3534
int main() {
3635
Variable a{2}, b{3}, c{4};
3736
Plus d{a, b}; Times e{d, c};
38-
std::cout << e.value() << "\n"; // prints "20"
37+
std::cout << e.value() << "\n"; // 20
3938
}
40-
// end::all[]
39+
// end::content[]

doc/modules/ROOT/examples/ast_virtual_function_2.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,8 @@
55

66
// clang-format off
77

8-
#include <iostream>
9-
108
// tag::all[]
9+
#include <iostream>
1110

1211
struct Node {
1312
virtual ~Node() {}

doc/modules/ROOT/nav.adoc

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
* xref:motivation.adoc[Motivation]
2-
* Basic Features
3-
** xref:hello_world.adoc[Hello World]
4-
** xref:smart_pointers.adoc[Smart Pointers]
5-
** xref:performance.adoc[Performance]
6-
** xref:headers_namespaces.adoc[Headers and Namespaces]
7-
** xref:friendship.adoc[Friendship]
8-
** xref:multiple_dispatch.adoc[Multiple Dispatch]
1+
* xref:introduction.adoc[Introduction]
2+
* xref:basics.adoc[Basics]
3+
* xref:smart_pointers.adoc[Smart Pointers]
4+
* xref:performance.adoc[Performance]
5+
* xref:headers_namespaces.adoc[Headers and Namespaces]
6+
* xref:friendship.adoc[Friendship]
7+
* xref:multiple_dispatch.adoc[Multiple Dispatch]
98
* Advanced Features
109
** xref:core_api.adoc[Core API]
1110
** xref:virtual_ptr_alt.adoc[Virtual Pointer Alternatives]

doc/modules/ROOT/pages/basics.adoc

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
:exampledir: ../example
2+
3+
## Basics
4+
5+
An _open-method_ is a free-standing function that takes one or more _virtual_
6+
_parameters_. When it is called, it forwards to an _overrider_ selected by
7+
examining the dynamic type of the virtual parameters.
8+
9+
If this sounds like a virtual function, that's because because an open-method
10+
with one virtual parameter is equivalent to a virtual function - with a big
11+
difference: it exists outside of classes.
12+
13+
A virtual parameter is in the form `virtual_ptr<C>`. It is a pointer-like class
14+
that points to an instance of class `C`.
15+
16+
To create an open-method that implements the `postfix` operation, we use the
17+
xref:BOOST_OPENMETHOD.adoc[BOOST_OPENMETHOD] macro:
18+
19+
```c++
20+
BOOST_OPENMETHOD(
21+
postfix, (virtual_ptr<const Node> node, std::ostream& os), void);
22+
```
23+
24+
This method is called `postfix`. It takes one virtual parameter, `node`, and one
25+
non-virtual parameter, `os`. It returns `void`. The macro generates the
26+
following function:
27+
28+
```c++
29+
inline auto postfix(virtual_ptr<const Node> node, std::ostream& os) -> void {
30+
// examine the type of *node
31+
// select an overrider
32+
// call it
33+
}
34+
```
35+
36+
Before we can call the method, we need to define overriders. For this we use the
37+
xref:BOOST_OPENMETHOD_OVERRIDE.adoc[BOOST_OPENMETHOD_OVERRIDE] macro:
38+
39+
```c++
40+
BOOST_OPENMETHOD_OVERRIDE(
41+
postfix, (virtual_ptr<const Variable> var, std::ostream& os), void) {
42+
os << var->v;
43+
}
44+
```
45+
46+
The overrider must have virtual parameters in the same position as in the
47+
method, and they must point to an object of the same class as in the method, or
48+
a class derived from it. The other parameters must have the same types as in the
49+
method.
50+
51+
Let's look at another overrider:
52+
53+
```c++
54+
BOOST_OPENMETHOD_OVERRIDE(
55+
postfix, (virtual_ptr<const Plus> plus, std::ostream& os), void) {
56+
postfix(plus->left, os);
57+
os << ' ';
58+
postfix(plus->right, os);
59+
}
60+
```
61+
62+
This one calls `postfix` recursively to print the left and right
63+
sub-expressions. Note that we call the method just like an ordinary function.
64+
65+
`postfix` expects a `virtual_ptr<const Node>`, and we are passing it a _plain_
66+
_reference_ to a `Plus` object. This works because `virtual_ptr` has conversion
67+
constructors from plain references or pointers to an object, or from other
68+
`virtual_ptr` to compatible classes.
69+
70+
There are two more things we need to do.
71+
72+
OpenMethod is a library, not a compiler. It needs to be aware of all the classes
73+
that may be used as virtual parameters, and in method calls, and their
74+
inheritance relationships. We do this using the
75+
xref:BOOST_OPENMETHOD_CLASSES.adoc[BOOST_OPENMETHOD_CLASSES] macro:
76+
77+
```c++
78+
BOOST_OPENMETHOD_CLASSES(Node, Variable, Plus, Times);
79+
```
80+
81+
Classes can be registered multiple times, in any order, and incrementally. Every
82+
direct base of a class must appear together with it in at least one call to
83+
`BOOST_OPENMETHOD_CLASSES`. This enables the library to deduce the complete
84+
inheritance lattice.
85+
86+
Finally, we need to call `boost::openmethod::initialize()` before the first call
87+
to an open-method. This builds the dispatch tables used during method calls. It
88+
is typically done once, at the very beginning of main, and requires the
89+
inclusion of `<boost/openmethod/initialize.hpp>`.
90+
91+
```c++
92+
#include <boost/openmethod/initialize.hpp>
93+
94+
int main() {
95+
boost::openmethod::initialize();
96+
// ...
97+
}
98+
```
99+
100+
Putting it all together:
101+
102+
[source,cpp]
103+
----
104+
include::{examplesdir}/ast.cpp[tag=content]
105+
----

doc/modules/ROOT/pages/hello_world.adoc

Lines changed: 0 additions & 99 deletions
This file was deleted.

0 commit comments

Comments
 (0)