@@ -14,3 +14,96 @@ includes the headers for the compiler, `shared_ptr` and `unique_ptr`. For
1414example, here is the last iteration of the [ AST
1515example] ( https://godbolt.org/z/cPjzfanc8 ) from the tutorial. Don't forget to
1616turn on optimizations (` -O2 -DNDEBUG ` ) and to select the Boost library.
17+
18+ ## OpenMethod vs Boost.TypeErasure
19+
20+ OpenMethod and TypeErasure exist in the same space: runtime polymorphic systems
21+ that offer a solution to the Expression Problem.
22+
23+ Thanks to BOOST_TYPE_ERASURE_FREE, we can add operations to existing classes,
24+ without the need to modify them. And of course we can add new classes to
25+ existing operations, by providing the required functions on them.
26+
27+ However, we quickly hits a wall, and this is related to the fact that in B.TE
28+ polymorphism is imbued to a "magic" handle, ` any ` , whereas in OpenMethod,
29+ polymorphism is attached to the object itself.
30+
31+ Let's look at an example. Consider a matrix library, which contains several
32+ matrix subtypes (let's limit ourselves to "ordinary" and "symmetric") and
33+ operations (let's just focus on transposition).
34+
35+ Here is (what I believe is) a plausible design:
36+
37+ ``` c++
38+ #include < boost/mpl/vector.hpp>
39+ #include < boost/type_erasure/any.hpp>
40+ #include < boost/type_erasure/free.hpp>
41+ #include < boost/type_erasure/typeid_of.hpp>
42+ #include < boost/core/demangle.hpp>
43+ #include < iostream>
44+
45+ namespace mpl = boost::mpl;
46+ using namespace boost::type_erasure;
47+
48+ BOOST_TYPE_ERASURE_FREE(transpose);
49+
50+ struct ordinary_matrix_impl {
51+ virtual ~ ordinary_matrix_impl() { /* ... * / }
52+ std::size_t rows, cols;
53+ std::vector<double > elements; // rows x cols doubles
54+ };
55+
56+ struct symmetric_matrix_impl {
57+ virtual ~ symmetric_matrix_impl() { /* ... * / }
58+ std::size_t rows; // cols == rows
59+ std::vector<double > elements; // rows doubles
60+ };
61+
62+ struct matrix {
63+ any< mpl::vector<copy_constructible< > , has_transpose<matrix(_ self&)>, typeid_ <>>> impl;
64+ };
65+
66+ auto transpose(matrix m) {
67+ return transpose(m.impl);
68+ }
69+
70+ auto transpose(ordinary_matrix_impl& m) {
71+ return matrix{ordinary_matrix_impl()};
72+ }
73+
74+ auto transpose(symmetric_matrix_impl& m) {
75+ return matrix{m};
76+ }
77+
78+ auto main() -> int {
79+ {
80+ matrix m{ordinary_matrix_impl()};
81+ auto t = transpose(m);
82+ std::cout << boost::core::demangle(typeid_of(t.impl).name()) << "\n";
83+ // ordinary_matrix_impl
84+ }
85+
86+ {
87+ matrix m{symmetric_matrix_impl()};
88+ auto t = transpose(m);
89+ std::cout << boost::core::demangle(typeid_of(t.impl).name()) << "\n";
90+ // symmetric_matrix_impl
91+ }
92+
93+ return 0 ;
94+ }
95+ ```
96+
97+ ([ Compiler Explorer] ( https://godbolt.org/z/613Eo5zGP )
98+
99+ We were able to add new behavior to existing classes (the "impl" classes)
100+ without needing to modify them. This is promising.
101+
102+ Here is the equivalent using open-methods:
103+
104+ ``` c++
105+ ```
106+
107+
108+
109+ We can also add serialization to JSON:
0 commit comments