8 | 12 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,19 @@ |
1 |
+digraph "Crany" |
|
2 |
+{ |
|
3 |
+ edge [dir=back,arrowtail=empty] |
|
4 |
+ |
|
5 |
+ "ModelSelf<Model<Self>>" -> "Concept<ModelSelf<Model<Self>>>" [label="self()"] |
|
6 |
+ "Concept<ModelSelf<Model<Self>>>" -> "Model" [label="static relays"] |
|
7 |
+ |
|
8 |
+ "ConceptSelf" -> "Concept<ConceptSelf>" [label="recursive self()"] |
|
9 |
+ "Concept<ConceptSelf>" -> "CloneConcept" [label="dynamic definitions"] |
|
10 |
+ |
|
11 |
+ "CranySelf<Crany<Concept>>" -> "Concept<CranySelf<Crany<Concept>>>" [label="self()"] |
|
12 |
+ "Concept<CranySelf<Crany<Concept>>>" -> "Crany<Concept>" [label="static relays"] |
|
13 |
+ |
|
14 |
+ "CloneConcept" -> "ModelSelf<Model<Self>>" [label="clone()" constraint=false] |
|
15 |
+ |
|
16 |
+ "Crany<Concept>" -> "CloneConcept" [label="self_" arrowtail=diamond constraint=false] |
|
17 |
+ |
|
18 |
+ "Model" -> "Self" [label="self_" arrowtail=diamond] |
|
19 |
+} |
2 | 22 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,137 @@ |
1 |
+<?xml version="1.0" encoding="UTF-8" standalone="no"?> |
|
2 |
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" |
|
3 |
+ "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> |
|
4 |
+<!-- Generated by graphviz version 2.43.0 (0) |
|
5 |
+ --> |
|
6 |
+<!-- Title: Crany Pages: 1 --> |
|
7 |
+<svg width="787pt" height="328pt" |
|
8 |
+ viewBox="0.00 0.00 787.00 328.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> |
|
9 |
+<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 324)"> |
|
10 |
+<title>Crany</title> |
|
11 |
+<polygon fill="white" stroke="transparent" points="-4,4 -4,-324 783,-324 783,4 -4,4"/> |
|
12 |
+<text text-anchor="middle" x="389.5" y="-304.8" font-family="Arial" font-size="14.00" fill="grey">Crany</text> |
|
13 |
+<!-- ModelSelf<Model<Self>> --> |
|
14 |
+<g id="node1" class="node"> |
|
15 |
+<title>ModelSelf<Model<Self>></title> |
|
16 |
+<path fill="none" stroke="black" d="M192.5,-297C192.5,-297 45.5,-297 45.5,-297 39.5,-297 33.5,-291 33.5,-285 33.5,-285 33.5,-273 33.5,-273 33.5,-267 39.5,-261 45.5,-261 45.5,-261 192.5,-261 192.5,-261 198.5,-261 204.5,-267 204.5,-273 204.5,-273 204.5,-285 204.5,-285 204.5,-291 198.5,-297 192.5,-297"/> |
|
17 |
+<text text-anchor="middle" x="119" y="-275.3" font-family="Arial" font-size="14.00">ModelSelf<Model<Self>></text> |
|
18 |
+</g> |
|
19 |
+<!-- Concept<ModelSelf<Model<Self>>> --> |
|
20 |
+<g id="node2" class="node"> |
|
21 |
+<title>Concept<ModelSelf<Model<Self>>></title> |
|
22 |
+<path fill="none" stroke="black" d="M226,-210C226,-210 12,-210 12,-210 6,-210 0,-204 0,-198 0,-198 0,-186 0,-186 0,-180 6,-174 12,-174 12,-174 226,-174 226,-174 232,-174 238,-180 238,-186 238,-186 238,-198 238,-198 238,-204 232,-210 226,-210"/> |
|
23 |
+<text text-anchor="middle" x="119" y="-188.3" font-family="Arial" font-size="14.00">Concept<ModelSelf<Model<Self>>></text> |
|
24 |
+</g> |
|
25 |
+<!-- ModelSelf<Model<Self>>->Concept<ModelSelf<Model<Self>>> --> |
|
26 |
+<g id="edge1" class="edge"> |
|
27 |
+<title>ModelSelf<Model<Self>>->Concept<ModelSelf<Model<Self>>></title> |
|
28 |
+<path fill="none" stroke="black" d="M119,-250.73C119,-237.42 119,-221.81 119,-210.18"/> |
|
29 |
+<polygon fill="none" stroke="black" points="115.5,-250.8 119,-260.8 122.5,-250.8 115.5,-250.8"/> |
|
30 |
+<text text-anchor="middle" x="137.5" y="-231.8" font-family="Times,serif" font-size="14.00">self()</text> |
|
31 |
+</g> |
|
32 |
+<!-- Model --> |
|
33 |
+<g id="node3" class="node"> |
|
34 |
+<title>Model</title> |
|
35 |
+<path fill="none" stroke="black" d="M134,-123C134,-123 104,-123 104,-123 98,-123 92,-117 92,-111 92,-111 92,-99 92,-99 92,-93 98,-87 104,-87 104,-87 134,-87 134,-87 140,-87 146,-93 146,-99 146,-99 146,-111 146,-111 146,-117 140,-123 134,-123"/> |
|
36 |
+<text text-anchor="middle" x="119" y="-101.3" font-family="Arial" font-size="14.00">Model</text> |
|
37 |
+</g> |
|
38 |
+<!-- Concept<ModelSelf<Model<Self>>>->Model --> |
|
39 |
+<g id="edge2" class="edge"> |
|
40 |
+<title>Concept<ModelSelf<Model<Self>>>->Model</title> |
|
41 |
+<path fill="none" stroke="black" d="M119,-163.73C119,-150.42 119,-134.81 119,-123.18"/> |
|
42 |
+<polygon fill="none" stroke="black" points="115.5,-163.8 119,-173.8 122.5,-163.8 115.5,-163.8"/> |
|
43 |
+<text text-anchor="middle" x="163" y="-144.8" font-family="Times,serif" font-size="14.00">static relays</text> |
|
44 |
+</g> |
|
45 |
+<!-- Self --> |
|
46 |
+<g id="node4" class="node"> |
|
47 |
+<title>Self</title> |
|
48 |
+<path fill="none" stroke="black" d="M134,-36C134,-36 104,-36 104,-36 98,-36 92,-30 92,-24 92,-24 92,-12 92,-12 92,-6 98,0 104,0 104,0 134,0 134,0 140,0 146,-6 146,-12 146,-12 146,-24 146,-24 146,-30 140,-36 134,-36"/> |
|
49 |
+<text text-anchor="middle" x="119" y="-14.3" font-family="Arial" font-size="14.00">Self</text> |
|
50 |
+</g> |
|
51 |
+<!-- Model->Self --> |
|
52 |
+<g id="edge3" class="edge"> |
|
53 |
+<title>Model->Self</title> |
|
54 |
+<path fill="none" stroke="black" d="M119,-74.74C119,-61.88 119,-47.23 119,-36.18"/> |
|
55 |
+<polygon fill="black" stroke="black" points="119,-74.8 123,-80.8 119,-86.8 115,-80.8 119,-74.8"/> |
|
56 |
+<text text-anchor="middle" x="135.5" y="-57.8" font-family="Times,serif" font-size="14.00">self_</text> |
|
57 |
+</g> |
|
58 |
+<!-- ConceptSelf --> |
|
59 |
+<g id="node5" class="node"> |
|
60 |
+<title>ConceptSelf</title> |
|
61 |
+<path fill="none" stroke="black" d="M453,-297C453,-297 387,-297 387,-297 381,-297 375,-291 375,-285 375,-285 375,-273 375,-273 375,-267 381,-261 387,-261 387,-261 453,-261 453,-261 459,-261 465,-267 465,-273 465,-273 465,-285 465,-285 465,-291 459,-297 453,-297"/> |
|
62 |
+<text text-anchor="middle" x="420" y="-275.3" font-family="Arial" font-size="14.00">ConceptSelf</text> |
|
63 |
+</g> |
|
64 |
+<!-- Concept<ConceptSelf> --> |
|
65 |
+<g id="node6" class="node"> |
|
66 |
+<title>Concept<ConceptSelf></title> |
|
67 |
+<path fill="none" stroke="black" d="M486.5,-210C486.5,-210 353.5,-210 353.5,-210 347.5,-210 341.5,-204 341.5,-198 341.5,-198 341.5,-186 341.5,-186 341.5,-180 347.5,-174 353.5,-174 353.5,-174 486.5,-174 486.5,-174 492.5,-174 498.5,-180 498.5,-186 498.5,-186 498.5,-198 498.5,-198 498.5,-204 492.5,-210 486.5,-210"/> |
|
68 |
+<text text-anchor="middle" x="420" y="-188.3" font-family="Arial" font-size="14.00">Concept<ConceptSelf></text> |
|
69 |
+</g> |
|
70 |
+<!-- ConceptSelf->Concept<ConceptSelf> --> |
|
71 |
+<g id="edge4" class="edge"> |
|
72 |
+<title>ConceptSelf->Concept<ConceptSelf></title> |
|
73 |
+<path fill="none" stroke="black" d="M420,-250.73C420,-237.42 420,-221.81 420,-210.18"/> |
|
74 |
+<polygon fill="none" stroke="black" points="416.5,-250.8 420,-260.8 423.5,-250.8 416.5,-250.8"/> |
|
75 |
+<text text-anchor="middle" x="474" y="-231.8" font-family="Times,serif" font-size="14.00">recursive self()</text> |
|
76 |
+</g> |
|
77 |
+<!-- CloneConcept --> |
|
78 |
+<g id="node7" class="node"> |
|
79 |
+<title>CloneConcept</title> |
|
80 |
+<path fill="none" stroke="black" d="M459,-123C459,-123 381,-123 381,-123 375,-123 369,-117 369,-111 369,-111 369,-99 369,-99 369,-93 375,-87 381,-87 381,-87 459,-87 459,-87 465,-87 471,-93 471,-99 471,-99 471,-111 471,-111 471,-117 465,-123 459,-123"/> |
|
81 |
+<text text-anchor="middle" x="420" y="-101.3" font-family="Arial" font-size="14.00">CloneConcept</text> |
|
82 |
+</g> |
|
83 |
+<!-- Concept<ConceptSelf>->CloneConcept --> |
|
84 |
+<g id="edge5" class="edge"> |
|
85 |
+<title>Concept<ConceptSelf>->CloneConcept</title> |
|
86 |
+<path fill="none" stroke="black" d="M420,-163.73C420,-150.42 420,-134.81 420,-123.18"/> |
|
87 |
+<polygon fill="none" stroke="black" points="416.5,-163.8 420,-173.8 423.5,-163.8 416.5,-163.8"/> |
|
88 |
+<text text-anchor="middle" x="490.5" y="-144.8" font-family="Times,serif" font-size="14.00">dynamic definitions</text> |
|
89 |
+</g> |
|
90 |
+<!-- CloneConcept->ModelSelf<Model<Self>> --> |
|
91 |
+<g id="edge6" class="edge"> |
|
92 |
+<title>CloneConcept->ModelSelf<Model<Self>></title> |
|
93 |
+<path fill="none" stroke="black" d="M367.44,-127.24C340.96,-139.12 309.02,-155.3 283,-174 264.62,-187.2 265.19,-196.54 247,-210 219.28,-230.5 184.57,-248.53 158.29,-260.87"/> |
|
94 |
+<polygon fill="none" stroke="black" points="369.19,-130.29 376.94,-123.06 366.37,-123.89 369.19,-130.29"/> |
|
95 |
+<text text-anchor="middle" x="307.5" y="-188.3" font-family="Times,serif" font-size="14.00">clone()</text> |
|
96 |
+</g> |
|
97 |
+<!-- CranySelf<Crany<Concept>> --> |
|
98 |
+<g id="node8" class="node"> |
|
99 |
+<title>CranySelf<Crany<Concept>></title> |
|
100 |
+<path fill="none" stroke="black" d="M733.5,-297C733.5,-297 562.5,-297 562.5,-297 556.5,-297 550.5,-291 550.5,-285 550.5,-285 550.5,-273 550.5,-273 550.5,-267 556.5,-261 562.5,-261 562.5,-261 733.5,-261 733.5,-261 739.5,-261 745.5,-267 745.5,-273 745.5,-273 745.5,-285 745.5,-285 745.5,-291 739.5,-297 733.5,-297"/> |
|
101 |
+<text text-anchor="middle" x="648" y="-275.3" font-family="Arial" font-size="14.00">CranySelf<Crany<Concept>></text> |
|
102 |
+</g> |
|
103 |
+<!-- Concept<CranySelf<Crany<Concept>>> --> |
|
104 |
+<g id="node9" class="node"> |
|
105 |
+<title>Concept<CranySelf<Crany<Concept>>></title> |
|
106 |
+<path fill="none" stroke="black" d="M767,-210C767,-210 529,-210 529,-210 523,-210 517,-204 517,-198 517,-198 517,-186 517,-186 517,-180 523,-174 529,-174 529,-174 767,-174 767,-174 773,-174 779,-180 779,-186 779,-186 779,-198 779,-198 779,-204 773,-210 767,-210"/> |
|
107 |
+<text text-anchor="middle" x="648" y="-188.3" font-family="Arial" font-size="14.00">Concept<CranySelf<Crany<Concept>>></text> |
|
108 |
+</g> |
|
109 |
+<!-- CranySelf<Crany<Concept>>->Concept<CranySelf<Crany<Concept>>> --> |
|
110 |
+<g id="edge7" class="edge"> |
|
111 |
+<title>CranySelf<Crany<Concept>>->Concept<CranySelf<Crany<Concept>>></title> |
|
112 |
+<path fill="none" stroke="black" d="M648,-250.73C648,-237.42 648,-221.81 648,-210.18"/> |
|
113 |
+<polygon fill="none" stroke="black" points="644.5,-250.8 648,-260.8 651.5,-250.8 644.5,-250.8"/> |
|
114 |
+<text text-anchor="middle" x="666.5" y="-231.8" font-family="Times,serif" font-size="14.00">self()</text> |
|
115 |
+</g> |
|
116 |
+<!-- Crany<Concept> --> |
|
117 |
+<g id="node10" class="node"> |
|
118 |
+<title>Crany<Concept></title> |
|
119 |
+<path fill="none" stroke="black" d="M695.5,-123C695.5,-123 600.5,-123 600.5,-123 594.5,-123 588.5,-117 588.5,-111 588.5,-111 588.5,-99 588.5,-99 588.5,-93 594.5,-87 600.5,-87 600.5,-87 695.5,-87 695.5,-87 701.5,-87 707.5,-93 707.5,-99 707.5,-99 707.5,-111 707.5,-111 707.5,-117 701.5,-123 695.5,-123"/> |
|
120 |
+<text text-anchor="middle" x="648" y="-101.3" font-family="Arial" font-size="14.00">Crany<Concept></text> |
|
121 |
+</g> |
|
122 |
+<!-- Concept<CranySelf<Crany<Concept>>>->Crany<Concept> --> |
|
123 |
+<g id="edge8" class="edge"> |
|
124 |
+<title>Concept<CranySelf<Crany<Concept>>>->Crany<Concept></title> |
|
125 |
+<path fill="none" stroke="black" d="M648,-163.73C648,-150.42 648,-134.81 648,-123.18"/> |
|
126 |
+<polygon fill="none" stroke="black" points="644.5,-163.8 648,-173.8 651.5,-163.8 644.5,-163.8"/> |
|
127 |
+<text text-anchor="middle" x="692" y="-144.8" font-family="Times,serif" font-size="14.00">static relays</text> |
|
128 |
+</g> |
|
129 |
+<!-- Crany<Concept>->CloneConcept --> |
|
130 |
+<g id="edge9" class="edge"> |
|
131 |
+<title>Crany<Concept>->CloneConcept</title> |
|
132 |
+<path fill="none" stroke="black" d="M575.88,-105C541.85,-105 502.04,-105 471.17,-105"/> |
|
133 |
+<polygon fill="black" stroke="black" points="576.12,-105 582.12,-101 588.12,-105 582.12,-109 576.12,-105"/> |
|
134 |
+<text text-anchor="middle" x="529.75" y="-111.8" font-family="Times,serif" font-size="14.00">self_</text> |
|
135 |
+</g> |
|
136 |
+</g> |
|
137 |
+</svg> |
0 | 138 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,139 @@ |
1 |
+#ifndef CRANY_HPP_ |
|
2 |
+#define CRANY_HPP_ |
|
3 |
+ |
|
4 |
+ |
|
5 |
+#include <memory> |
|
6 |
+#include <type_traits> |
|
7 |
+#include <cassert> |
|
8 |
+ |
|
9 |
+ |
|
10 |
+template<template<typename> class = std::is_void> |
|
11 |
+class Crany; |
|
12 |
+ |
|
13 |
+/// CranySelf |
|
14 |
+template<> |
|
15 |
+class Crany<> |
|
16 |
+{ |
|
17 |
+private: |
|
18 |
+ template<template<typename> class> friend class Crany; |
|
19 |
+ template<typename T> |
|
20 |
+ struct CranySelf |
|
21 |
+ { |
|
22 |
+ protected: |
|
23 |
+ auto & self() { return *((T *)this)->self_; } |
|
24 |
+ auto const & self() const { return *((T const *)this)->self_; } |
|
25 |
+ virtual ~CranySelf() = default; |
|
26 |
+ }; |
|
27 |
+}; |
|
28 |
+ |
|
29 |
+/// Crany |
|
30 |
+template<template<typename> class Concept> |
|
31 |
+class Crany final : public Concept<Crany<>::CranySelf<Crany<Concept>>> |
|
32 |
+{ |
|
33 |
+public: |
|
34 |
+ |
|
35 |
+ /// Special member functions |
|
36 |
+ template<typename Self> |
|
37 |
+ Crany(Self self) : self_{new Model<Self>(std::move(self))} {} |
|
38 |
+ Crany(Crany const & other) : self_(other.self_->clone()) {} |
|
39 |
+ Crany & operator=(Crany const & other) { return *this = Crany(other); } |
|
40 |
+ Crany(Crany && other) = default; |
|
41 |
+ Crany & operator=(Crany && other) = default; |
|
42 |
+ |
|
43 |
+private: |
|
44 |
+ |
|
45 |
+ /// CranySelf |
|
46 |
+ friend Crany<>::CranySelf<Crany<Concept>>; |
|
47 |
+ |
|
48 |
+ /// ConceptSelf |
|
49 |
+ struct ConceptSelf |
|
50 |
+ { |
|
51 |
+ protected: |
|
52 |
+ auto & self() { assert(!"Crany Concept non-virtual member function called"); return *(Concept<ConceptSelf> *)this; } |
|
53 |
+ auto const & self() const { assert(!"Crany Concept non-virtual member function called"); return *(Concept<ConceptSelf> const *)this; } |
|
54 |
+ virtual ~ConceptSelf() = default; |
|
55 |
+ }; |
|
56 |
+ |
|
57 |
+ /// CloneConcept |
|
58 |
+ struct CloneConcept : Concept<ConceptSelf> |
|
59 |
+ { |
|
60 |
+ virtual CloneConcept * clone() const = 0; |
|
61 |
+ }; |
|
62 |
+ |
|
63 |
+ /// ModelSelf |
|
64 |
+ template<typename T> |
|
65 |
+ struct ModelSelf : CloneConcept |
|
66 |
+ { |
|
67 |
+ protected: |
|
68 |
+ auto & self() { return ((T *)this)->self_; } |
|
69 |
+ auto const & self() const { return ((T const *)this)->self_; } |
|
70 |
+ }; |
|
71 |
+ |
|
72 |
+ /// Model |
|
73 |
+ template<typename Self> |
|
74 |
+ struct Model final : Concept<ModelSelf<Model<Self>>> |
|
75 |
+ { |
|
76 |
+ Model(Self self) : self_{std::move(self)} {} |
|
77 |
+ CloneConcept * clone() const { return new Model<Self>(*this); } |
|
78 |
+ Self self_; |
|
79 |
+ }; |
|
80 |
+ |
|
81 |
+ /// Self |
|
82 |
+ std::unique_ptr<CloneConcept> self_; |
|
83 |
+ |
|
84 |
+ /// crany_cast |
|
85 |
+ template<typename T, typename Crany> friend T const * crany_cast(Crany const * crany) noexcept; |
|
86 |
+ template<typename T, typename Crany> friend T * crany_cast(Crany * crany) noexcept; |
|
87 |
+ template<typename T, typename Crany> friend T crany_cast(Crany const & crany); |
|
88 |
+ template<typename T, typename Crany> friend T crany_cast(Crany & crany); |
|
89 |
+ template<typename T, typename Crany> friend T crany_cast(Crany && crany); |
|
90 |
+}; |
|
91 |
+ |
|
92 |
+/// bad_crany_cast |
|
93 |
+class bad_crany_cast : public std::bad_cast |
|
94 |
+{ |
|
95 |
+}; |
|
96 |
+ |
|
97 |
+/// crany_cast |
|
98 |
+template<typename T, typename Crany> |
|
99 |
+T const * crany_cast(Crany const * crany) noexcept |
|
100 |
+{ |
|
101 |
+ if (!crany) |
|
102 |
+ return nullptr; |
|
103 |
+ using Model = typename Crany::Model<T>; |
|
104 |
+ if (auto * model = dynamic_cast<Model *>(crany->self_.get())) |
|
105 |
+ return &model->self_; |
|
106 |
+ return nullptr; |
|
107 |
+} |
|
108 |
+template<typename T, typename Crany> |
|
109 |
+T * crany_cast(Crany * crany) noexcept |
|
110 |
+{ |
|
111 |
+ return const_cast<T *>(*const_cast<T const *>(crany)); |
|
112 |
+} |
|
113 |
+template<typename T, typename Crany> |
|
114 |
+T crany_cast(Crany const & crany) |
|
115 |
+{ |
|
116 |
+ using U = std::remove_cv_t<std::remove_reference_t<T>>; |
|
117 |
+ if (auto p = crany_cast<U>(&crany)) |
|
118 |
+ return static_cast<T>(*p); |
|
119 |
+ throw bad_crany_cast(); // TODO |
|
120 |
+} |
|
121 |
+template<typename T, typename Crany> |
|
122 |
+T crany_cast(Crany & crany) |
|
123 |
+{ |
|
124 |
+ using U = std::remove_cv_t<std::remove_reference_t<T>>; |
|
125 |
+ if (auto p = crany_cast<U>(&crany)) |
|
126 |
+ return static_cast<T>(*p); |
|
127 |
+ throw bad_crany_cast(); // TODO |
|
128 |
+} |
|
129 |
+template<typename T, typename Crany> |
|
130 |
+T crany_cast(Crany && crany) |
|
131 |
+{ |
|
132 |
+ using U = std::remove_cv_t<std::remove_reference_t<T>>; |
|
133 |
+ if (auto p = crany_cast<U>(&crany)) |
|
134 |
+ return static_cast<T>(std::move(*p)); |
|
135 |
+ throw bad_crany_cast(); // TODO |
|
136 |
+} |
|
137 |
+ |
|
138 |
+ |
|
139 |
+#endif // CRANY_HPP_ |
0 | 140 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,59 @@ |
1 |
+#include "crany.hpp" |
|
2 |
+ |
|
3 |
+#include <cmath> |
|
4 |
+#include <iostream> |
|
5 |
+#include <vector> |
|
6 |
+ |
|
7 |
+ |
|
8 |
+auto constexpr pi = std::acos(-1.0F); |
|
9 |
+ |
|
10 |
+ |
|
11 |
+struct Circle |
|
12 |
+{ |
|
13 |
+ float radius; |
|
14 |
+ void scale(float scale) { radius *= scale; } |
|
15 |
+ float area() const { return pi*radius*radius; } |
|
16 |
+ float circumference() const { return 2.0F*pi*radius; } |
|
17 |
+}; |
|
18 |
+ |
|
19 |
+struct Rectangle |
|
20 |
+{ |
|
21 |
+ float side1; |
|
22 |
+ float side2; |
|
23 |
+ void scale(float scale) { side1 *= scale; side2 *= scale; } |
|
24 |
+ float area() const { return side1*side2; } |
|
25 |
+}; |
|
26 |
+ |
|
27 |
+ |
|
28 |
+template<typename Self> |
|
29 |
+struct ShapeConcept : Self |
|
30 |
+{ |
|
31 |
+ using Self::self; |
|
32 |
+ virtual void scale(float value) { return self().scale(value); } |
|
33 |
+ virtual float area() const { return self().area(); } |
|
34 |
+}; |
|
35 |
+ |
|
36 |
+using Shape = Crany<ShapeConcept>; |
|
37 |
+using Shapes = std::vector<Shape>; |
|
38 |
+ |
|
39 |
+ |
|
40 |
+int main() |
|
41 |
+{ |
|
42 |
+ static_assert(std::is_standard_layout <Circle>{}, "Circle not is standard layout"); |
|
43 |
+ static_assert(std::is_trivially_copyable<Circle>{}, "Circle not is trivially copyable"); |
|
44 |
+ |
|
45 |
+ auto shapes = Shapes{ |
|
46 |
+ Circle{1.0F}, |
|
47 |
+ Rectangle{2.0F, 3.0F}, |
|
48 |
+ }; |
|
49 |
+ shapes.push_back(shapes.front()); |
|
50 |
+ shapes.back().scale(2.0F); |
|
51 |
+ |
|
52 |
+ std::cout << std::boolalpha; |
|
53 |
+ for (auto const & shape : shapes) |
|
54 |
+ std::cout |
|
55 |
+ << shape.area() |
|
56 |
+ << " " |
|
57 |
+ << bool(crany_cast<Circle>(&shape)) |
|
58 |
+ << "\n"; |
|
59 |
+} |