source: source/ariba/utility/vtypes/vfacade.hpp@ 10700

Last change on this file since 10700 was 10700, checked in by Michael Tänzer, 12 years ago

Merge CMake branch into trunk

File size: 5.4 KB
Line 
1// [License]
2// The FreeBSD License
3//
4// Copyright (c) 2008-2009 Sebastian Mies <mies@edcft.de>
5//
6// Sebastian Mies
7// Gebhardstrasse 25
8// 76137 Karlsruhe
9// Germany
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25// BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32// [License]
33
34#ifndef VFACADE_HPP_
35#define VFACADE_HPP_
36
37//--- USAGE INFORMATION --------------------------------------------------------
38//
39// This header is used to easily implement a virtual facade design pattern. It
40// allows to specify a virtual wrapper interface to a non-virtual class. Look
41// at this example:
42//
43// <code>
44// // unspecified version
45// class to_string_definition : public vfacade_interface {
46// public:
47// virtual string to_string() const {
48// return "UNIMPLEMENTED: to_string()";
49// };
50// };
51//
52// // delegation version
53// template<class T>
54// class vfacade_delegation<to_string_definition, T> :
55// public to_string_definition {
56// public:
57// virtual string to_string() const {
58// return get<T>().to_string();
59// }
60// };
61//
62// // final type
63// typedef vfacade<to_string_definition> vto_string;
64// </code>
65//
66// The to_string_definition specifies an unimplemented facade interface. Its
67// necessary for this class not to be pure-virtual. The vfacade_delegation
68// specialization implements a delegation any another non-virtual class T.
69// Finally the facade type is defined by using the vfacade template. Now,
70// we can use this facade, like in the following example:
71//
72// <code>
73// class A {
74// public:
75// string to_string() {
76// return "a hello from class A";
77// }
78// };
79//
80// void main() {
81// A something;
82// vto_string to_str = something;
83// cout << to_str->to_string() << endl;
84// }
85// </code>
86//
87// This example outputs "a hello from class A" by using the virtual facade. As
88// defined class A does not need to know about the facade -- it just implements
89// the needed methods. The to_string method is transparently bound to the
90// facade by the delegation implementation.
91//
92// The purpose of this virtual facade is simple: whenever you need a abstract
93// representation of non-virtual structures you can simply use a virtual facade.
94// It carries a vtable with the delegation to the non-virtual methods and a
95// pointer to the original object. Therefore it binds a vtable to a pointer
96// so vtable information is stored with the pointer and not with the object
97// itself.
98//
99//------------------------------------------------------------------------------
100
101// forward declaration
102template<class X, class Y>
103class vfacade_delegation;
104
105/**
106 * This class template implements a virtual facade using a defined interface
107 * X and a certain delegation specialization of vfascade_delegation<X,Y>.
108 *
109 * @author Sebastian Mies <mies@edcft.de>
110 */
111template<class X>
112class vfacade {
113private:
114 X value;
115
116public:
117 vfacade() {
118 }
119
120 template<class Y>
121 vfacade(const Y& _value) {
122 vfacade_delegation<X, Y> v;
123 v.set(_value);
124 memcpy(&value, &v, sizeof(X));
125 }
126
127 template<class Y>
128 vfacade<X>& operator=(const Y& _value) {
129 vfacade_delegation<X, Y> v;
130 v.set(_value);
131 memcpy(&value, &v, sizeof(X));
132 return *this;
133 }
134
135 vfacade(const vfacade<X>& v) {
136 memcpy(&value, &v.value, sizeof(X));
137 }
138
139 vfacade<X>& operator=(const vfacade<X>& v ) {
140 memcpy(&value, &v.value, sizeof(X));
141 return *this;
142 }
143
144 X* operator->() {
145 return &value;
146 }
147
148 const X* operator->() const {
149 return &value;
150 }
151};
152
153/**
154 * This class is used as base class for virtual facade interfaces.
155 *
156 * @author Sebastian Mies <mies@edcft.de>
157 */
158class vfacade_interface {
159 template<class X> friend class vfacade;
160
161private:
162 void* value;
163
164protected:
165 template<class X> X& get() const {
166 return *((X*) value);
167 }
168 template<class X> void set(X& v) {
169 value = (void*) &v;
170 }
171
172public:
173 vfacade_interface() :
174 value(NULL) {
175 }
176
177 bool is_unspecified() const {
178 return value == NULL;
179 }
180
181 template<class Y>
182 Y* ptr() {
183 return (Y*)value;
184 }
185
186 template<class Y>
187 const Y* ptr() const {
188 return (Y*)value;
189 }
190
191 template<class Y>
192 Y& cast_to() {
193 return *ptr<Y>();
194 }
195
196 template<class Y>
197 const Y& cast_to() const {
198 return *ptr<Y>();
199 }
200};
201
202/**
203 * This class is the base template for further delegation specializations.
204 *
205 * @author Sebastian Mies <mies@edcft.de>
206 */
207template<class T, class Y>
208class vfacade_delegation: public T {
209
210};
211
212#endif
Note: See TracBrowser for help on using the repository browser.