Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/trunk/src/libraries/util/MultiType.h @ 9550

Last change on this file since 9550 was 9550, checked in by landauf, 11 years ago

merged testing branch back to trunk. unbelievable it took me 13 months to finish this chore…

  • Property svn:eol-style set to native
File size: 27.9 KB
Line 
1/*
2 *   ORXONOX - the hottest 3D action shooter ever to exist
3 *                    > www.orxonox.net <
4 *
5 *
6 *   License notice:
7 *
8 *   This program is free software; you can redistribute it and/or
9 *   modify it under the terms of the GNU General Public License
10 *   as published by the Free Software Foundation; either version 2
11 *   of the License, or (at your option) any later version.
12 *
13 *   This program is distributed in the hope that it will be useful,
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 *   GNU General Public License for more details.
17 *
18 *   You should have received a copy of the GNU General Public License
19 *   along with this program; if not, write to the Free Software
20 *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 *   Author:
23 *      Fabian 'x3n' Landau
24 *   Co-authors:
25 *      ...
26 *
27 */
28
29/**
30    @defgroup MultiType MultiType
31    @ingroup Util
32*/
33
34/**
35    @file
36    @ingroup MultiType
37    @brief Declaration of the MultiType and some helper constructs.
38
39    @anchor MultiTypeExamples
40
41    The MultiType can hold a value of one of the following types:
42     - all primitives (int, float, bool, etc.)
43     - all pointers (void* and T*)
44     - std::string
45     - Vector2, Vector3, Vector4
46     - Quaternion
47     - ColourValue
48     - Radian, Degree
49
50    The MultiType has an internal "type" determined by the first assigned value, using one of these ways:
51     - @ref orxonox::MultiType::MultiType "The constructor"
52     - The assignment operator= (orxonox::MultiType::operator=())
53     - @ref orxonox::MultiType::set() "set(value)"
54
55    If you assign another value of another type, the MultiType keeps "its" type and
56    converts the new value to the old type.
57
58    If you want to change the type, there are three possibilities:
59     - @ref orxonox::MultiType::convert "convert<T>()" sets the type to T and converts the currently assigned value
60     - @ref orxonox::MultiType::reset "reset<T>()" sets the type to T and resets the value to zero using zeroise<T>()
61     - force<T>(value) assigns a new value and changes the type to T.
62
63    Examples:
64    @code
65    MultiType a = 10;       // a has now the type int and the value 10
66    a.set("3.14");          // a has still the type int and "3.14" gets converted, therefore the value is now 3
67    a.force<float>("3.14"); // a has now the type float and "3.14" gets converted to 3.14f
68    a.convert<bool>();      // converts 3.14f to bool, which is true
69    a = false;              // assigns false, this is equivalent to a.setValue(false)
70    @endcode
71
72    You can pass a MultiType to a function as an argument, even if the argument is
73    not of type MultiType. This works, because the MultiType is automatically converted
74    to the right type.
75
76    Example:
77    @code
78    void myfunction(int value)
79    {
80        orxout() << "doubled value is " << (2 * value) << endl;
81    }
82
83    MultiType a = "50";        // Note: We assigned a string
84    myfunction(a);             // a is converted to int and passed to the function, which prints "value is 100"
85    @endcode
86
87    Note however that it is of course quite expensive to convert values, especially std::string <-> value.
88    So if you can, always assign a value with the right type to avoid conversion.
89
90    @note
91    Whenever a value gets converted, there is a boolean return value telling you whether it was
92    successful or not. If it wasn't a zero value is assigned with the help of zeroise<T>().
93*/
94
95#ifndef _MultiType_H__
96#define _MultiType_H__
97
98#include "UtilPrereqs.h"
99
100#include <cassert>
101#include <string>
102#include <OgreVector2.h>
103#include <OgreVector3.h>
104#include <OgreVector4.h>
105#include <OgreQuaternion.h>
106#include <OgreColourValue.h>
107#include <loki/TypeTraits.h>
108#include "Math.h"
109#include "mbool.h"
110
111namespace orxonox
112{
113    /**
114        @brief The MultiType can hold a value of many possible types and convert them to other types.
115
116        The following types are supported by the MultiType:
117         - all primitves
118         - all pointers
119         - string
120         - Vector2, Vector3, Vector4
121         - Quaternion
122         - ColourValue
123         - Radian, Degree
124
125        For more information and some examples see the description @ref MultiTypeExamples "here".
126
127        @see MultiType.h
128    */
129    class _UtilExport MultiType
130    {
131        _UtilExport friend std::ostream& operator<<(std::ostream& outstream, const MultiType& mt);
132        template <typename T> friend class MT_Value;
133
134        struct Type
135        {
136            /**
137                @brief Enum of all possible types of a MultiType.
138            */
139            enum Enum
140            {
141                Null,
142                Char,
143                UnsignedChar,
144                Short,
145                UnsignedShort,
146                Int,
147                UnsignedInt,
148                Long,
149                UnsignedLong,
150                LongLong,
151                UnsignedLongLong,
152                Float,
153                Double,
154                LongDouble,
155                Bool,
156                VoidPointer,
157                String,
158                Vector2,
159                Vector3,
160                Vector4,
161                ColourValue,
162                Quaternion,
163                Radian,
164                Degree
165            };
166        };
167
168    public:
169        /**
170            @brief MT_ValueBase is an almost pure virtual baseclass of MT_Value<T>, which holds the value of the MultiType.
171            This class is only used within the MultiType.
172        */
173        class _UtilExport MT_ValueBase
174        {
175        public:
176            inline MT_ValueBase(void* data, Type::Enum type) : type_(type), bLastConversionSuccessful(true), data_(data) {}
177            inline virtual ~MT_ValueBase() {}
178
179            virtual MT_ValueBase* clone() const = 0;
180
181            virtual void reset() = 0;
182
183            /// Returns the type of the current value.
184            inline const Type::Enum& getType() const { return this->type_; }
185            /// Returns true if the type of the stored value is T.
186            template <typename T> inline bool isType() const { return false; }
187
188            /// Checks whether the value is a default one.
189            inline bool lastConversionSuccessful()   const { return this->bLastConversionSuccessful; }
190
191            virtual bool setValue(const char& value)                 = 0;
192            virtual bool setValue(const unsigned char& value)        = 0;
193            virtual bool setValue(const short& value)                = 0;
194            virtual bool setValue(const unsigned short& value)       = 0;
195            virtual bool setValue(const int& value)                  = 0;
196            virtual bool setValue(const unsigned int& value)         = 0;
197            virtual bool setValue(const long& value)                 = 0;
198            virtual bool setValue(const unsigned long& value)        = 0;
199            virtual bool setValue(const long long& value)            = 0;
200            virtual bool setValue(const unsigned long long& value)   = 0;
201            virtual bool setValue(const float& value)                = 0;
202            virtual bool setValue(const double& value)               = 0;
203            virtual bool setValue(const long double& value)          = 0;
204            virtual bool setValue(const bool& value)                 = 0;
205            virtual bool setValue(      void* const& value)          = 0;
206            virtual bool setValue(const std::string& value)          = 0;
207            virtual bool setValue(const orxonox::Vector2& value)     = 0;
208            virtual bool setValue(const orxonox::Vector3& value)     = 0;
209            virtual bool setValue(const orxonox::Vector4& value)     = 0;
210            virtual bool setValue(const orxonox::ColourValue& value) = 0;
211            virtual bool setValue(const orxonox::Quaternion& value)  = 0;
212            virtual bool setValue(const orxonox::Radian& value)      = 0;
213            virtual bool setValue(const orxonox::Degree& value)      = 0;
214
215            virtual bool setValue(const MultiType& other)            = 0;
216
217            virtual bool getValue(char*                 value) const = 0;
218            virtual bool getValue(unsigned char*        value) const = 0;
219            virtual bool getValue(short*                value) const = 0;
220            virtual bool getValue(unsigned short*       value) const = 0;
221            virtual bool getValue(int*                  value) const = 0;
222            virtual bool getValue(unsigned int*         value) const = 0;
223            virtual bool getValue(long*                 value) const = 0;
224            virtual bool getValue(unsigned long*        value) const = 0;
225            virtual bool getValue(long long*            value) const = 0;
226            virtual bool getValue(unsigned long long*   value) const = 0;
227            virtual bool getValue(float*                value) const = 0;
228            virtual bool getValue(double*               value) const = 0;
229            virtual bool getValue(long double*          value) const = 0;
230            virtual bool getValue(bool*                 value) const = 0;
231            virtual bool getValue(void**                value) const = 0;
232            virtual bool getValue(std::string*          value) const = 0;
233            virtual bool getValue(orxonox::Vector2*     value) const = 0;
234            virtual bool getValue(orxonox::Vector3*     value) const = 0;
235            virtual bool getValue(orxonox::Vector4*     value) const = 0;
236            virtual bool getValue(orxonox::ColourValue* value) const = 0;
237            virtual bool getValue(orxonox::Quaternion*  value) const = 0;
238            virtual bool getValue(orxonox::Radian*      value) const = 0;
239            virtual bool getValue(orxonox::Degree*      value) const = 0;
240
241            template <typename T> T get() const
242            {
243                if (this->isType<T>())
244                    return *reinterpret_cast<const T*>(this->data_);
245                else
246                {
247                    T value;
248                    this->getValue(&value);
249                    return value;
250                }
251            }
252
253            virtual void toString(std::ostream& outstream) const = 0;
254
255            virtual void importData(uint8_t*& mem) = 0;
256            virtual void exportData(uint8_t*& mem) const = 0;
257            virtual uint8_t getSize() const = 0;
258
259            Type::Enum type_;               ///< The type of the current value
260            bool bLastConversionSuccessful; ///< True if the last conversion was successful
261            void* data_;                    ///< For direct access to the value if the type is known
262        };
263
264        public:
265            static const MultiType Null;
266
267            /// Default constructor: Assigns no value and no type. The type will be determined by the first assignment of a value.
268            inline MultiType()                       : value_(0) { }
269            /// Constructor: Assigns the given value and sets the type.
270            template <typename V>
271            inline MultiType(const V& value)         : value_(0) { this->set(value); }
272            /// Copyconstructor: Assigns value and type of the other MultiType.
273            inline MultiType(const MultiType& other) : value_(0) { this->set(other); }
274
275            /// Destructor: Deletes the MT_Value.
276            inline ~MultiType() { if (this->value_) { delete this->value_; } }
277
278            /// Assigns a new value. The value will be converted to the current type of the MultiType.
279            template <typename V> inline MultiType& operator=(const V& value)         { this->set(value); return (*this); }
280            /// Assigns a pointer.
281            template <typename V> inline MultiType& operator=(V* value)               { this->set(value); return (*this); }
282            /// Assigns the value of the other MultiType and converts it to the current type of the MultiType.
283            inline                       MultiType& operator=(const MultiType& other) { this->set(other); return (*this); }
284
285            /// Assigns the given value and converts it to the current type.
286            template <typename V> inline bool set(const V& value)
287            {
288                if (this->value_)
289                    return this->value_->setValue(value);
290
291                this->assignValue(value);
292                return true;
293            }
294            /// Assigns a pointer.
295            template <typename V> inline bool set(V* value)
296            {
297                if (this->value_)
298                    return this->value_->setValue(static_cast<void*>(const_cast<typename Loki::TypeTraits<V>::UnqualifiedType*>(value)));
299
300                this->assignValue(static_cast<void*>(const_cast<typename Loki::TypeTraits<V>::UnqualifiedType*>(value)));
301                return true;
302            }
303            /// Assigns the value of the other MultiType and converts it to the current type.
304            inline bool set(const MultiType& other)
305            {
306                if (this->value_)
307                    return this->value_->setValue(other);
308                else if (other.value_)
309                    this->value_ = other.value_->clone();
310                return true;
311            }
312
313            /// Changes the type to T and assigns the new value (which might be of another type than T - it gets converted).
314            template <typename T, typename V> inline bool force(const V& value)
315            {
316                this->reset<T>();
317                return this->set(value);
318            }
319
320            /// Copies the other MultiType by assigning value and type.
321            inline void copy(const MultiType& other)
322            {
323                if (this == &other)
324                    return;
325                if (this->value_)
326                    delete this->value_;
327                this->value_ = (other.value_) ? other.value_->clone() : 0;
328            }
329
330            /// Converts the current value to type T.
331            template <typename T> inline bool convert() { return this->force<T>(MultiType(*this)); }
332
333            /// Resets value and type. Type will be void afterwards and null() returns true.
334            inline void reset() { if (this->value_) delete this->value_; this->value_ = 0; }
335            /// Resets the value and changes the internal type to T.
336            template <typename T> inline void reset() { this->assignValue(typename Loki::TypeTraits<T>::UnqualifiedReferredType()); }
337            /// Current value gets overridden with default zero value
338            inline void resetValue() { if (this->value_) this->value_->reset(); }
339
340            /// Returns true if the type of the current value is T.
341            template <typename T> inline bool isType() const { return (this->value_ ? this->value_->isType<T>() : false); }
342            std::string getTypename() const;
343
344            /// Checks whether the last conversion was successful
345            inline bool lastConversionSuccessful() const { return !this->value_ || this->value_->lastConversionSuccessful(); }
346
347            /// Checks if the MT contains no value.
348            inline bool null() const { return !this->value_; }
349
350            inline operator char()                 const { return (this->value_ ? this->value_->get<char>()                 : 0); }
351            inline operator unsigned char()        const { return (this->value_ ? this->value_->get<unsigned char>()        : 0); }
352            inline operator short()                const { return (this->value_ ? this->value_->get<short>()                : 0); }
353            inline operator unsigned short()       const { return (this->value_ ? this->value_->get<unsigned short>()       : 0); }
354            inline operator int()                  const { return (this->value_ ? this->value_->get<int>()                  : 0); }
355            inline operator unsigned int()         const { return (this->value_ ? this->value_->get<unsigned int>()         : 0); }
356            inline operator long()                 const { return (this->value_ ? this->value_->get<long>()                 : 0); }
357            inline operator unsigned long()        const { return (this->value_ ? this->value_->get<unsigned long>()        : 0); }
358            inline operator long long()            const { return (this->value_ ? this->value_->get<long long>()            : 0); }
359            inline operator unsigned long long()   const { return (this->value_ ? this->value_->get<unsigned long long>()   : 0); }
360            inline operator float()                const { return (this->value_ ? this->value_->get<float>()                : 0); }
361            inline operator double()               const { return (this->value_ ? this->value_->get<double>()               : 0); }
362            inline operator long double()          const { return (this->value_ ? this->value_->get<long double>()          : 0); }
363            inline operator bool()                 const { return (this->value_ ? this->value_->get<bool>()                 : 0); }
364            inline operator void*()                const { return (this->value_ ? this->value_->get<void*>()                : 0); }
365            inline operator std::string()          const { return (this->value_ ? this->value_->get<std::string>()          : NilValue<std::string>()); }
366            inline operator orxonox::Vector2()     const { return (this->value_ ? this->value_->get<orxonox::Vector2>()     : NilValue<orxonox::Vector2>()); }
367            inline operator orxonox::Vector3()     const { return (this->value_ ? this->value_->get<orxonox::Vector3>()     : NilValue<orxonox::Vector3>()); }
368            inline operator orxonox::Vector4()     const { return (this->value_ ? this->value_->get<orxonox::Vector4>()     : NilValue<orxonox::Vector4>()); }
369            inline operator orxonox::ColourValue() const { return (this->value_ ? this->value_->get<orxonox::ColourValue>() : NilValue<orxonox::ColourValue>()); }
370            inline operator orxonox::Quaternion()  const { return (this->value_ ? this->value_->get<orxonox::Quaternion>()  : NilValue<orxonox::Quaternion>()); }
371            inline operator orxonox::Radian()      const { return (this->value_ ? this->value_->get<orxonox::Radian>()      : NilValue<orxonox::Radian>()); }
372            inline operator orxonox::Degree()      const { return (this->value_ ? this->value_->get<orxonox::Degree>()      : NilValue<orxonox::Degree>()); }
373            /// Returns the current value, converted to a T* pointer.
374            template <class T> operator T*() const { return (static_cast<T*>(this->operator void*())); }
375
376            /// Assigns the value to the given pointer. The value gets converted if the types don't match.
377            template <typename T> inline bool getValue(T* value) const { if (this->value_) { return this->value_->getValue(value); } return false; }
378
379            /// Returns the current value, converted to the requested type.
380            template <typename T> inline T get() const { return *this; }
381
382
383            ///////////////////////////////
384            // network-related functions //
385            ///////////////////////////////
386            /// Saves the value of the MT to a bytestream (pointed at by mem) and increases mem pointer by size of MT
387            inline void exportData(uint8_t*& mem) const
388            {
389                assert(sizeof(Type::Enum) <= 8);
390                *static_cast<uint8_t*>(mem) = this->getType();
391                mem += sizeof(uint8_t);
392                this->value_->exportData(mem);
393            }
394            /// Loads the value of the MT from a bytestream (pointed at by mem) and increases mem pointer by size of MT
395            inline void importData(uint8_t*& mem)
396            {
397                assert(sizeof(Type::Enum) <= 8);
398                this->setType(static_cast<Type::Enum>(*static_cast<uint8_t*>(mem)));
399                mem += sizeof(uint8_t);
400                this->value_->importData(mem);
401            }
402            /// Saves the value of the MT to a bytestream and increases pointer to bytestream by size of MT
403            inline uint8_t*& operator<<(uint8_t*& mem)
404            {
405                importData(mem);
406                return mem;
407            }
408            /// Loads the value of the MT to a bytestream and increases pointer to bytestream by size of MT
409            inline void operator>>(uint8_t*& mem) const
410            {
411                exportData(mem);
412            }
413            inline uint32_t getNetworkSize() const
414            {
415                assert(this->value_);
416                return this->value_->getSize() + sizeof(uint8_t);
417            }
418
419        private:
420            /// Assigns a new value by changing type and creating a new container.
421            template <typename T> inline void assignValue(const T& value)
422            {
423                if (this->isType<T>())
424                    this->value_->setValue(value);
425                else
426                    this->changeValueContainer(value);
427            }
428            /// Assigns a new value by changing type and creating a new container (overload for pointers).
429            template <typename T> inline void assignValue(T* const& value)
430            {
431                if (this->isType<void*>())
432                    this->value_->setValue(static_cast<void*>(value));
433                else
434                    this->changeValueContainer<void*>(value);
435            }
436
437            /// Resets the value and changes the internal type to the given type.
438            inline void setType(Type::Enum type) { this->reset(); this->convert(type); this->resetValue(); }
439            /// Returns the current type.
440            inline Type::Enum getType() const { return (this->value_) ? this->value_->type_ : Type::Null; }
441            /// Converts the current value to the given type.
442            bool convert(Type::Enum type);
443
444            /// Changes the value container.
445            template <typename T> inline void changeValueContainer(const T& value)
446            {
447                if (this->value_)
448                    delete this->value_;
449                this->createNewValueContainer(value);
450            }
451            /// Creates a new value container (works only with specialized types).
452            template <typename T> inline void createNewValueContainer(const T& value) { /* STATIC ASSERT */ *****value; return false; }
453
454            MT_ValueBase* value_; //!< A pointer to the value container
455    };
456
457    /// Puts the MultiType on a stream by using the native << operator of the current type.
458    _UtilExport inline std::ostream& operator<<(std::ostream& outstream, const MultiType& mt)
459    {
460        if (mt.value_)
461            mt.value_->toString(outstream);
462        return outstream;
463    }
464
465    template <> inline bool MultiType::MT_ValueBase::isType<char>()                 const { return this->type_ == Type::Char;             }
466    template <> inline bool MultiType::MT_ValueBase::isType<unsigned char>()        const { return this->type_ == Type::UnsignedChar;     }
467    template <> inline bool MultiType::MT_ValueBase::isType<short>()                const { return this->type_ == Type::Short;            }
468    template <> inline bool MultiType::MT_ValueBase::isType<unsigned short>()       const { return this->type_ == Type::UnsignedShort;    }
469    template <> inline bool MultiType::MT_ValueBase::isType<int>()                  const { return this->type_ == Type::Int;              }
470    template <> inline bool MultiType::MT_ValueBase::isType<unsigned int>()         const { return this->type_ == Type::UnsignedInt;      }
471    template <> inline bool MultiType::MT_ValueBase::isType<long>()                 const { return this->type_ == Type::Long;             }
472    template <> inline bool MultiType::MT_ValueBase::isType<unsigned long>()        const { return this->type_ == Type::UnsignedLong;     }
473    template <> inline bool MultiType::MT_ValueBase::isType<long long>()            const { return this->type_ == Type::LongLong;         }
474    template <> inline bool MultiType::MT_ValueBase::isType<unsigned long long>()   const { return this->type_ == Type::UnsignedLongLong; }
475    template <> inline bool MultiType::MT_ValueBase::isType<float>()                const { return this->type_ == Type::Float;            }
476    template <> inline bool MultiType::MT_ValueBase::isType<double>()               const { return this->type_ == Type::Double;           }
477    template <> inline bool MultiType::MT_ValueBase::isType<long double>()          const { return this->type_ == Type::LongDouble;       }
478    template <> inline bool MultiType::MT_ValueBase::isType<bool>()                 const { return this->type_ == Type::Bool;             }
479    template <> inline bool MultiType::MT_ValueBase::isType<void*>()                const { return this->type_ == Type::VoidPointer;      }
480    template <> inline bool MultiType::MT_ValueBase::isType<std::string>()          const { return this->type_ == Type::String;           }
481    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector2>()     const { return this->type_ == Type::Vector2;          }
482    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector3>()     const { return this->type_ == Type::Vector3;          }
483    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector4>()     const { return this->type_ == Type::Vector4;          }
484    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::ColourValue>() const { return this->type_ == Type::ColourValue;      }
485    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Quaternion>()  const { return this->type_ == Type::Quaternion;       }
486    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Radian>()      const { return this->type_ == Type::Radian;           }
487    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Degree>()      const { return this->type_ == Type::Degree;           }
488
489    template <> inline bool MultiType::set(const char* value)  { return this->set(std::string(value)); }
490    template <> inline bool MultiType::set(const mbool& value) { return this->set((bool)value); }
491
492    // Spezializations for void
493    template <> inline bool MultiType::isType<void>() const { return this->null(); }
494    template <> inline bool MultiType::convert<void>() { this->reset(); return true; }
495
496    template <> _UtilExport void MultiType::createNewValueContainer(const char& value);
497    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned char& value);
498    template <> _UtilExport void MultiType::createNewValueContainer(const short& value);
499    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned short& value);
500    template <> _UtilExport void MultiType::createNewValueContainer(const int& value);
501    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned int& value);
502    template <> _UtilExport void MultiType::createNewValueContainer(const long& value);
503    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned long& value);
504    template <> _UtilExport void MultiType::createNewValueContainer(const long long& value);
505    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned long long& value);
506    template <> _UtilExport void MultiType::createNewValueContainer(const float& value);
507    template <> _UtilExport void MultiType::createNewValueContainer(const double& value);
508    template <> _UtilExport void MultiType::createNewValueContainer(const bool& value);
509    template <> _UtilExport void MultiType::createNewValueContainer(const long double& value);
510    template <> _UtilExport void MultiType::createNewValueContainer(      void* const& value);
511    template <> _UtilExport void MultiType::createNewValueContainer(const std::string& value);
512    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector2& value);
513    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector3& value);
514    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector4& value);
515    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::ColourValue& value);
516    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Quaternion& value);
517    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Radian& value);
518    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Degree& value);
519}
520
521#endif /* _MultiType_H__ */
Note: See TracBrowser for help on using the repository browser.