Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/core2/src/util/MultiTypePrimitive.cc @ 1001

Last change on this file since 1001 was 1001, checked in by landauf, 16 years ago

ok, be aware, here comes a big one. people with weak nerves should probably better look away or take some serious drugs.
this update includes partial and explicit class template specialization, partial and explicit specialized template function overloading, template meta programming and a simple typecast.
yeah right, a typecast. but let me explain the whole story from the beginning.

it all started with a simple problem: i had a double in a MultiType and wanted a float, but i always got 0. what was the problem? the conversion 'MultiType to anyting' was handled by the Converter class in util/Convert.h and the Converter was specialized for strings, multitypes, vectors and so on, but not for int, float, bool, …
so i've first wanted to implement a typecast as default, but this was a bad idea because it doesn't work for almost every generic type.
implementing an explicit specialization for every possible pair of primitives (did you ever happened to use an unsigned short? or a long double? no? ignorants :D) would have been a simple but ugly solution.
but there were other problems: if there's a rule to convert a string into anything and another rule to convert anything into an int - what happens if you want to convert a string into an int? compiler error! …ambiguous partial template specialization.
so i've spent days and nights to find a solution. this is my 5th try or so and i'm still really unsure if it works, but it's the first version i want to commit to have at least a backup.
if you're interested in looking at the code you better wait until i've cleaned up the whole thing, it's a real mess. and i want to do further tests, but now i'm tired. good night ;)

File size: 11.1 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *
4 *
5 *   License notice:
6 *
7 *   This program is free software; you can redistribute it and/or
8 *   modify it under the terms of the GNU General Public License
9 *   as published by the Free Software Foundation; either version 2
10 *   of the License, or (at your option) any later version.
11 *
12 *   This program is distributed in the hope that it will be useful,
13 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
14 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 *   GNU General Public License for more details.
16 *
17 *   You should have received a copy of the GNU General Public License
18 *   along with this program; if not, write to the Free Software
19 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 *
21 *   Author:
22 *      Fabian 'x3n' Landau
23 *   Co-authors:
24 *      ...
25 *
26 *   Inspiration: MultiType by Benjamin Grauer
27 */
28
29#include "MultiTypePrimitive.h"
30#include "Convert.h"
31
32MultiTypePrimitive::MultiTypePrimitive(MultiType type)
33{
34    this->type_ = type;
35
36    if (type == MT_void)
37        this->value_.void_ = 0;
38    else if (type == MT_int)
39        this->value_.int_ = 0;
40    else if (type == MT_uint)
41        this->value_.uint_ = 0;
42    else if (type == MT_char)
43        this->value_.char_ = 0;
44    else if (type == MT_uchar)
45        this->value_.uchar_ = 0;
46    else if (type == MT_short)
47        this->value_.short_ = 0;
48    else if (type == MT_ushort)
49        this->value_.ushort_ = 0;
50    else if (type == MT_long)
51        this->value_.long_ = 0;
52    else if (type == MT_ulong)
53        this->value_.ulong_ = 0;
54    else if (type == MT_float)
55        this->value_.float_ = 0.0;
56    else if (type == MT_double)
57        this->value_.double_ = 0.0;
58    else if (type == MT_longdouble)
59        this->value_.longdouble_ = 0.0;
60    else if (type == MT_bool)
61        this->value_.bool_ = false;
62    else
63        this->value_.void_ = 0;
64}
65
66bool MultiTypePrimitive::operator==(const MultiTypePrimitive& mtp) const
67{
68    if (this->type_ == mtp.type_)
69    {
70        if (this->type_ == MT_void)
71            return (this->value_.void_ == mtp.value_.void_);
72        else if (this->type_ == MT_int)
73            return (this->value_.int_ == mtp.value_.int_);
74        else if (this->type_ == MT_uint)
75            return (this->value_.uint_ == mtp.value_.uint_);
76        else if (this->type_ == MT_char)
77            return (this->value_.char_ == mtp.value_.char_);
78        else if (this->type_ == MT_uchar)
79            return (this->value_.uchar_ == mtp.value_.uchar_);
80        else if (this->type_ == MT_short)
81            return (this->value_.short_ == mtp.value_.short_);
82        else if (this->type_ == MT_ushort)
83            return (this->value_.ushort_ == mtp.value_.ushort_);
84        else if (this->type_ == MT_long)
85            return (this->value_.long_ == mtp.value_.long_);
86        else if (this->type_ == MT_ulong)
87            return (this->value_.ulong_ == mtp.value_.ulong_);
88        else if (this->type_ == MT_float)
89            return (this->value_.float_ == mtp.value_.float_);
90        else if (this->type_ == MT_double)
91            return (this->value_.double_ == mtp.value_.double_);
92        else if (this->type_ == MT_longdouble)
93            return (this->value_.longdouble_ == mtp.value_.longdouble_);
94        else if (this->type_ == MT_bool)
95            return (this->value_.bool_ == mtp.value_.bool_);
96    }
97
98    return false;
99}
100
101bool MultiTypePrimitive::operator!=(const MultiTypePrimitive& mtp) const
102{
103    if (this->type_ == mtp.type_)
104    {
105        if (this->type_ == MT_void)
106            return (this->value_.void_ != mtp.value_.void_);
107        else if (this->type_ == MT_int)
108            return (this->value_.int_ != mtp.value_.int_);
109        else if (this->type_ == MT_uint)
110            return (this->value_.uint_ != mtp.value_.uint_);
111        else if (this->type_ == MT_char)
112            return (this->value_.char_ != mtp.value_.char_);
113        else if (this->type_ == MT_uchar)
114            return (this->value_.uchar_ != mtp.value_.uchar_);
115        else if (this->type_ == MT_short)
116            return (this->value_.short_ != mtp.value_.short_);
117        else if (this->type_ == MT_ushort)
118            return (this->value_.ushort_ != mtp.value_.ushort_);
119        else if (this->type_ == MT_long)
120            return (this->value_.long_ != mtp.value_.long_);
121        else if (this->type_ == MT_ulong)
122            return (this->value_.ulong_ != mtp.value_.ulong_);
123        else if (this->type_ == MT_float)
124            return (this->value_.float_ != mtp.value_.float_);
125        else if (this->type_ == MT_double)
126            return (this->value_.double_ != mtp.value_.double_);
127        else if (this->type_ == MT_longdouble)
128            return (this->value_.longdouble_ != mtp.value_.longdouble_);
129        else if (this->type_ == MT_bool)
130            return (this->value_.bool_ != mtp.value_.bool_);
131    }
132
133    return true;
134}
135
136MultiTypePrimitive::operator void*() const
137{ return (this->type_ == MT_void) ? this->value_.void_ : getConvertedValue<MultiTypePrimitive, void*>(*this, 0); }
138MultiTypePrimitive::operator int() const
139{ return (this->type_ == MT_int) ? this->value_.int_ : getConvertedValue<MultiTypePrimitive, int>(*this, 0); }
140MultiTypePrimitive::operator unsigned int() const
141{ return (this->type_ == MT_uint) ? this->value_.uint_ : getConvertedValue<MultiTypePrimitive, unsigned int>(*this, 0); }
142MultiTypePrimitive::operator char() const
143{ return (this->type_ == MT_char) ? this->value_.char_ : getConvertedValue<MultiTypePrimitive, char>(*this, 0); }
144MultiTypePrimitive::operator unsigned char() const
145{ return (this->type_ == MT_uchar) ? this->value_.uchar_ : getConvertedValue<MultiTypePrimitive, unsigned char>(*this, 0); }
146MultiTypePrimitive::operator short() const
147{ return (this->type_ == MT_short) ? this->value_.short_ : getConvertedValue<MultiTypePrimitive, short>(*this, 0); }
148MultiTypePrimitive::operator unsigned short() const
149{ return (this->type_ == MT_ushort) ? this->value_.ushort_ : getConvertedValue<MultiTypePrimitive, unsigned short>(*this, 0); }
150MultiTypePrimitive::operator long() const
151{ return (this->type_ == MT_long) ? this->value_.long_ : getConvertedValue<MultiTypePrimitive, long>(*this, 0); }
152MultiTypePrimitive::operator unsigned long() const
153{ return (this->type_ == MT_ulong) ? this->value_.ulong_ : getConvertedValue<MultiTypePrimitive, unsigned long>(*this, 0); }
154MultiTypePrimitive::operator float() const
155{ return (this->type_ == MT_float) ? this->value_.float_ : getConvertedValue<MultiTypePrimitive, float>(*this, 0); }
156MultiTypePrimitive::operator double() const
157{ return (this->type_ == MT_double) ? this->value_.double_ : getConvertedValue<MultiTypePrimitive, double>(*this, 0); }
158MultiTypePrimitive::operator long double() const
159{ return (this->type_ == MT_longdouble) ? this->value_.longdouble_ : getConvertedValue<MultiTypePrimitive, long double>(*this, 0); }
160MultiTypePrimitive::operator bool() const
161{ return (this->type_ == MT_bool) ? this->value_.bool_ : getConvertedValue<MultiTypePrimitive, bool>(*this, 0); }
162
163void MultiTypePrimitive::setValue(const MultiTypePrimitive& mtp)
164{
165    this->type_ = mtp.type_;
166    this->value_ = mtp.value_;
167}
168
169std::string MultiTypePrimitive::getTypename() const
170{
171    if (this->type_ == MT_void)
172        return "pointer";
173    else if (this->type_ == MT_int)
174        return "int";
175    else if (this->type_ == MT_uint)
176        return "unsigned int";
177    else if (this->type_ == MT_char)
178        return "char";
179    else if (this->type_ == MT_uchar)
180        return "unsigned char";
181    else if (this->type_ == MT_short)
182        return "short";
183    else if (this->type_ == MT_ushort)
184        return "unsigned short";
185    else if (this->type_ == MT_long)
186        return "long";
187    else if (this->type_ == MT_ulong)
188        return "unsigned long";
189    else if (this->type_ == MT_float)
190        return "float";
191    else if (this->type_ == MT_double)
192        return "double";
193    else if (this->type_ == MT_longdouble)
194        return "long double";
195    else if (this->type_ == MT_bool)
196        return "bool";
197    else
198        return "unknown";
199}
200
201std::string MultiTypePrimitive::toString() const
202{
203    std::string output;
204
205    if (this->type_ == MT_void)
206        ConvertValue(&output, this->value_.void_);
207    else if (this->type_ == MT_int)
208        ConvertValue(&output, this->value_.int_);
209    else if (this->type_ == MT_uint)
210        ConvertValue(&output, this->value_.uint_);
211    else if (this->type_ == MT_char)
212        ConvertValue(&output, this->value_.char_);
213    else if (this->type_ == MT_uchar)
214        ConvertValue(&output, this->value_.uchar_);
215    else if (this->type_ == MT_short)
216        ConvertValue(&output, this->value_.short_);
217    else if (this->type_ == MT_ushort)
218        ConvertValue(&output, this->value_.ushort_);
219    else if (this->type_ == MT_long)
220        ConvertValue(&output, this->value_.long_);
221    else if (this->type_ == MT_ulong)
222        ConvertValue(&output, this->value_.ulong_);
223    else if (this->type_ == MT_float)
224        ConvertValue(&output, this->value_.float_);
225    else if (this->type_ == MT_double)
226        ConvertValue(&output, this->value_.double_);
227    else if (this->type_ == MT_longdouble)
228        ConvertValue(&output, this->value_.longdouble_);
229    else if (this->type_ == MT_bool)
230        ConvertValue(&output, this->value_.bool_);
231
232    return output;
233}
234
235bool MultiTypePrimitive::fromString(const std::string value)
236{
237    if (this->type_ == MT_void)
238        return ConvertValue(&this->value_.void_, value, (void*)0);
239    else if (this->type_ == MT_int)
240        return ConvertValue(&this->value_.int_, value, (int)0);
241    else if (this->type_ == MT_uint)
242        return ConvertValue(&this->value_.uint_, value, (unsigned int)0);
243    else if (this->type_ == MT_char)
244        return ConvertValue(&this->value_.char_, value, (char)0);
245    else if (this->type_ == MT_uchar)
246        return ConvertValue(&this->value_.uchar_, value, (unsigned char)0);
247    else if (this->type_ == MT_short)
248        return ConvertValue(&this->value_.short_, value, (short)0);
249    else if (this->type_ == MT_ushort)
250        return ConvertValue(&this->value_.ushort_, value, (unsigned short)0);
251    else if (this->type_ == MT_long)
252        return ConvertValue(&this->value_.long_, value, (long)0);
253    else if (this->type_ == MT_ulong)
254        return ConvertValue(&this->value_.ulong_, value, (unsigned long)0);
255    else if (this->type_ == MT_float)
256        return ConvertValue(&this->value_.float_, value, (float)0.0);
257    else if (this->type_ == MT_double)
258        return ConvertValue(&this->value_.double_, value, (double)0.0);
259    else if (this->type_ == MT_longdouble)
260        return ConvertValue(&this->value_.longdouble_, value, (long double)0.0);
261    else if (this->type_ == MT_bool)
262        return ConvertValue(&this->value_.bool_, value, false);
263    else
264        return false;
265}
266
267std::ostream& operator<<(std::ostream& out, const MultiTypePrimitive& mtp)
268{
269    out << mtp.toString();
270    return out;
271}
Note: See TracBrowser for help on using the repository browser.