Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 11071 was 11071, checked in by landauf, 8 years ago

merged branch cpp11_v3 back to trunk

  • Property svn:eol-style set to native
File size: 28.1 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        /**
135            @brief Enum of all possible types of a MultiType.
136        */
137        enum class Type : uint8_t
138        {
139            Null,
140            Char,
141            UnsignedChar,
142            Short,
143            UnsignedShort,
144            Int,
145            UnsignedInt,
146            Long,
147            UnsignedLong,
148            LongLong,
149            UnsignedLongLong,
150            Float,
151            Double,
152            LongDouble,
153            Bool,
154            VoidPointer,
155            String,
156            Vector2,
157            Vector3,
158            Vector4,
159            ColourValue,
160            Quaternion,
161            Radian,
162            Degree
163        };
164
165    public:
166        /**
167            @brief MT_ValueBase is an almost pure virtual baseclass of MT_Value<T>, which holds the value of the MultiType.
168            This class is only used within the MultiType.
169        */
170        class _UtilExport MT_ValueBase
171        {
172        public:
173            inline MT_ValueBase(void* data, Type type) : type_(type), bLastConversionSuccessful(true), data_(data) {}
174            virtual inline ~MT_ValueBase() {}
175
176            virtual MT_ValueBase* clone() const = 0;
177
178            virtual void reset() = 0;
179
180            /// Returns the type of the current value.
181            inline const Type& getType() const { return this->type_; }
182
183            /// Returns true if the type of the stored value is T. Note: the actual implementations for all supported types are defined outside of the class.
184            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, bool>::type
185            inline /*bool*/ isType() const
186            {
187                // If you reach this code, you used MultiType with an unsupported type T
188                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
189                return false;
190            }
191            /// Implementation for enum classes: Returns true if the type of the stored value is the underlying type of T.
192            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, bool>::type
193            inline /*bool*/ isType() const
194            {
195                return this->isType<typename std::underlying_type<T>::type>();
196            }
197
198            /// Checks whether the value is a default one.
199            inline bool lastConversionSuccessful()   const { return this->bLastConversionSuccessful; }
200
201            virtual bool setValue(const char& value)                 = 0;
202            virtual bool setValue(const unsigned char& value)        = 0;
203            virtual bool setValue(const short& value)                = 0;
204            virtual bool setValue(const unsigned short& value)       = 0;
205            virtual bool setValue(const int& value)                  = 0;
206            virtual bool setValue(const unsigned int& value)         = 0;
207            virtual bool setValue(const long& value)                 = 0;
208            virtual bool setValue(const unsigned long& value)        = 0;
209            virtual bool setValue(const long long& value)            = 0;
210            virtual bool setValue(const unsigned long long& value)   = 0;
211            virtual bool setValue(const float& value)                = 0;
212            virtual bool setValue(const double& value)               = 0;
213            virtual bool setValue(const long double& value)          = 0;
214            virtual bool setValue(const bool& value)                 = 0;
215            virtual bool setValue(      void* const& value)          = 0;
216            virtual bool setValue(const std::string& value)          = 0;
217            virtual bool setValue(const orxonox::Vector2& value)     = 0;
218            virtual bool setValue(const orxonox::Vector3& value)     = 0;
219            virtual bool setValue(const orxonox::Vector4& value)     = 0;
220            virtual bool setValue(const orxonox::ColourValue& value) = 0;
221            virtual bool setValue(const orxonox::Quaternion& value)  = 0;
222            virtual bool setValue(const orxonox::Radian& value)      = 0;
223            virtual bool setValue(const orxonox::Degree& value)      = 0;
224
225            virtual bool setValue(const MultiType& other)            = 0;
226
227            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, bool>::type
228            inline /*bool*/ setValue(const T& value)
229            {
230                // If you reach this code, you used MultiType with an unsupported type T
231                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
232                return false;
233            }
234            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, bool>::type
235            inline /*bool*/ setValue(const T& value)
236            {
237                typedef typename std::underlying_type<T>::type UnderlyingType;
238                return this->setValue(reinterpret_cast<const UnderlyingType&>(value));
239            }
240
241            virtual bool getValue(char*                 value) const = 0;
242            virtual bool getValue(unsigned char*        value) const = 0;
243            virtual bool getValue(short*                value) const = 0;
244            virtual bool getValue(unsigned short*       value) const = 0;
245            virtual bool getValue(int*                  value) const = 0;
246            virtual bool getValue(unsigned int*         value) const = 0;
247            virtual bool getValue(long*                 value) const = 0;
248            virtual bool getValue(unsigned long*        value) const = 0;
249            virtual bool getValue(long long*            value) const = 0;
250            virtual bool getValue(unsigned long long*   value) const = 0;
251            virtual bool getValue(float*                value) const = 0;
252            virtual bool getValue(double*               value) const = 0;
253            virtual bool getValue(long double*          value) const = 0;
254            virtual bool getValue(bool*                 value) const = 0;
255            virtual bool getValue(void**                value) const = 0;
256            virtual bool getValue(std::string*          value) const = 0;
257            virtual bool getValue(orxonox::Vector2*     value) const = 0;
258            virtual bool getValue(orxonox::Vector3*     value) const = 0;
259            virtual bool getValue(orxonox::Vector4*     value) const = 0;
260            virtual bool getValue(orxonox::ColourValue* value) const = 0;
261            virtual bool getValue(orxonox::Quaternion*  value) const = 0;
262            virtual bool getValue(orxonox::Radian*      value) const = 0;
263            virtual bool getValue(orxonox::Degree*      value) const = 0;
264
265            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value, bool>::type
266            inline /*bool*/ getValue(T* value) const
267            {
268                // If you reach this code, you used MultiType with an unsupported type T
269                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
270                return false;
271            }
272            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value, bool>::type
273            inline /*bool*/ getValue(T* value) const
274            {
275                typedef typename std::underlying_type<T>::type UnderlyingType;
276                return this->getValue(reinterpret_cast<UnderlyingType*>(value));
277            }
278
279            template <typename T> T get() const
280            {
281                if (this->isType<T>())
282                    return *reinterpret_cast<const T*>(this->data_);
283                else
284                {
285                    T value;
286                    this->getValue(&value);
287                    return value;
288                }
289            }
290
291            virtual void toString(std::ostream& outstream) const = 0;
292
293            virtual void importData(uint8_t*& mem) = 0;
294            virtual void exportData(uint8_t*& mem) const = 0;
295            virtual uint8_t getSize() const = 0;
296
297            Type type_;                     ///< The type of the current value
298            bool bLastConversionSuccessful; ///< True if the last conversion was successful
299            void* data_;                    ///< For direct access to the value if the type is known
300        };
301
302        public:
303            static const MultiType Null;
304
305            /// Default constructor: Assigns no value and no type. The type will be determined by the first assignment of a value.
306            inline MultiType()                       : value_(nullptr) { }
307            /// Constructor: Assigns the given value and sets the type.
308            template <typename V>
309            inline MultiType(const V& value)         : value_(nullptr) { this->set(value); }
310            /// Copyconstructor: Assigns value and type of the other MultiType.
311            inline MultiType(const MultiType& other) : value_(nullptr) { this->set(other); }
312
313            /// Destructor: Deletes the MT_Value.
314            inline ~MultiType() { if (this->value_) { delete this->value_; } }
315
316            /// Assigns a new value. The value will be converted to the current type of the MultiType.
317            template <typename V> inline MultiType& operator=(const V& value)         { this->set(value); return (*this); }
318            /// Assigns a pointer.
319            template <typename V> inline MultiType& operator=(V* value)               { this->set(value); return (*this); }
320            /// Assigns the value of the other MultiType and converts it to the current type of the MultiType.
321            inline                       MultiType& operator=(const MultiType& other) { this->set(other); return (*this); }
322
323            /// Assigns the given value and converts it to the current type.
324            template <typename V> inline bool set(const V& value)
325            {
326                if (this->value_)
327                    return this->value_->setValue(value);
328
329                this->assignValue(value);
330                return true;
331            }
332            /// Assigns a pointer.
333            template <typename V> inline bool set(V* value)
334            {
335                if (this->value_)
336                    return this->value_->setValue(static_cast<void*>(const_cast<typename Loki::TypeTraits<V>::UnqualifiedType*>(value)));
337
338                this->assignValue(static_cast<void*>(const_cast<typename Loki::TypeTraits<V>::UnqualifiedType*>(value)));
339                return true;
340            }
341            /// Assigns the value of the other MultiType and converts it to the current type.
342            inline bool set(const MultiType& other)
343            {
344                if (this->value_)
345                    return this->value_->setValue(other);
346                else if (other.value_)
347                    this->value_ = other.value_->clone();
348                return true;
349            }
350
351            /// Changes the type to T and assigns the new value (which might be of another type than T - it gets converted).
352            template <typename T, typename V> inline bool force(const V& value)
353            {
354                this->reset<T>();
355                return this->set(value);
356            }
357
358            /// Copies the other MultiType by assigning value and type.
359            inline void copy(const MultiType& other)
360            {
361                if (this == &other)
362                    return;
363                if (this->value_)
364                    delete this->value_;
365                this->value_ = (other.value_) ? other.value_->clone() : nullptr;
366            }
367
368            /// Converts the current value to type T.
369            template <typename T> inline bool convert() { return this->force<T>(MultiType(*this)); }
370
371            /// Resets value and type. Type will be void afterwards and null() returns true.
372            inline void reset() { if (this->value_) delete this->value_; this->value_ = nullptr; }
373            /// Resets the value and changes the internal type to T.
374            template <typename T> inline void reset() { this->assignValue(typename Loki::TypeTraits<T>::UnqualifiedReferredType()); }
375            /// Current value gets overridden with default zero value
376            inline void resetValue() { if (this->value_) this->value_->reset(); }
377
378            /// Returns true if the type of the current value is T.
379            template <typename T> inline bool isType() const { return (this->value_ ? this->value_->isType<T>() : false); }
380            std::string getTypename() const;
381
382            /// Checks whether the last conversion was successful
383            inline bool lastConversionSuccessful() const { return !this->value_ || this->value_->lastConversionSuccessful(); }
384
385            /// Checks if the MT contains no value.
386            inline bool null() const { return !this->value_; }
387
388            /// Conversion operator for all types
389            template <class T> operator T()  const { return this->get<T>(); }
390
391            /// Assigns the value to the given pointer. The value gets converted if the types don't match.
392            template <typename T> inline bool getValue(T* value) const { if (this->value_) { return this->value_->getValue(value); } return false; }
393
394            /// Returns the current value, converted to the requested type.
395            template <typename T> /* for normal types */ typename std::enable_if<!std::is_pointer<T>::value, T>::type
396            inline /*T*/ get() const { return (this->value_ ? this->value_->get<T>() : NilValue<T>()); }
397            /// Returns the current value, converted to a pointer of the requested type.
398            template <typename T> /* for pointers */ typename std::enable_if<std::is_pointer<T>::value, T>::type
399            inline /*T*/ get() const { return this->value_ ? static_cast<T>(this->value_->get<void*>()) : nullptr; }
400
401
402            ///////////////////////////////
403            // network-related functions //
404            ///////////////////////////////
405            /// Saves the value of the MT to a bytestream (pointed at by mem) and increases mem pointer by size of MT
406            inline void exportData(uint8_t*& mem) const
407            {
408                assert(sizeof(Type) <= 8);
409                *static_cast<uint8_t*>(mem) = static_cast<uint8_t>(this->getType());
410                mem += sizeof(uint8_t);
411                this->value_->exportData(mem);
412            }
413            /// Loads the value of the MT from a bytestream (pointed at by mem) and increases mem pointer by size of MT
414            inline void importData(uint8_t*& mem)
415            {
416                assert(sizeof(Type) <= 8);
417                this->setType(static_cast<Type>(*static_cast<uint8_t*>(mem)));
418                mem += sizeof(uint8_t);
419                this->value_->importData(mem);
420            }
421            /// Saves the value of the MT to a bytestream and increases pointer to bytestream by size of MT
422            inline uint8_t*& operator<<(uint8_t*& mem)
423            {
424                importData(mem);
425                return mem;
426            }
427            /// Loads the value of the MT to a bytestream and increases pointer to bytestream by size of MT
428            inline void operator>>(uint8_t*& mem) const
429            {
430                exportData(mem);
431            }
432            inline uint32_t getNetworkSize() const
433            {
434                assert(this->value_);
435                return this->value_->getSize() + sizeof(uint8_t);
436            }
437
438        private:
439            /// Assigns a new value by changing type and creating a new container.
440            template <typename T> inline void assignValue(const T& value)
441            {
442                if (this->isType<T>())
443                    this->value_->setValue(value);
444                else
445                    this->changeValueContainer(value);
446            }
447            /// Assigns a new value by changing type and creating a new container (overload for pointers).
448            template <typename T> inline void assignValue(T* const& value)
449            {
450                if (this->isType<void*>())
451                    this->value_->setValue(static_cast<void*>(value));
452                else
453                    this->changeValueContainer<void*>(value);
454            }
455
456            /// Resets the value and changes the internal type to the given type.
457            inline void setType(Type type) { this->reset(); this->convert(type); this->resetValue(); }
458            /// Returns the current type.
459            inline Type getType() const { return (this->value_) ? this->value_->type_ : Type::Null; }
460            /// Converts the current value to the given type.
461            bool convert(Type type);
462
463            /// Changes the value container.
464            template <typename T> inline void changeValueContainer(const T& value)
465            {
466                if (this->value_)
467                    delete this->value_;
468                this->createNewValueContainer(value);
469            }
470            /// Creates a new value container (works only with specialized types).
471            template <typename T> /* for normal classes */ typename std::enable_if<!std::is_enum<T>::value>::type
472            inline /*void*/ createNewValueContainer(const T& value)
473            { 
474                // If you reach this code, you used MultiType with an unsupported type T
475                static_assert(sizeof(T) != sizeof(T), "No template specialization available for T");
476            }
477            /// Creates a new value container (implementation for enum classes that must be cast to the underlying type).
478            template <typename T> /* for enum classes */ typename std::enable_if<std::is_enum<T>::value>::type
479            inline /*void*/ createNewValueContainer(const T& value)
480            {
481                typedef typename std::underlying_type<T>::type UnderlyingType;
482                this->createNewValueContainer<UnderlyingType>(reinterpret_cast<const UnderlyingType&>(value));
483            }
484
485            MT_ValueBase* value_; //!< A pointer to the value container
486    };
487
488    /// Puts the MultiType on a stream by using the native << operator of the current type.
489    _UtilExport inline std::ostream& operator<<(std::ostream& outstream, const MultiType& mt)
490    {
491        if (mt.value_)
492            mt.value_->toString(outstream);
493        return outstream;
494    }
495
496    template <> inline bool MultiType::MT_ValueBase::isType<char>()                 const { return this->type_ == Type::Char;             }
497    template <> inline bool MultiType::MT_ValueBase::isType<unsigned char>()        const { return this->type_ == Type::UnsignedChar;     }
498    template <> inline bool MultiType::MT_ValueBase::isType<short>()                const { return this->type_ == Type::Short;            }
499    template <> inline bool MultiType::MT_ValueBase::isType<unsigned short>()       const { return this->type_ == Type::UnsignedShort;    }
500    template <> inline bool MultiType::MT_ValueBase::isType<int>()                  const { return this->type_ == Type::Int;              }
501    template <> inline bool MultiType::MT_ValueBase::isType<unsigned int>()         const { return this->type_ == Type::UnsignedInt;      }
502    template <> inline bool MultiType::MT_ValueBase::isType<long>()                 const { return this->type_ == Type::Long;             }
503    template <> inline bool MultiType::MT_ValueBase::isType<unsigned long>()        const { return this->type_ == Type::UnsignedLong;     }
504    template <> inline bool MultiType::MT_ValueBase::isType<long long>()            const { return this->type_ == Type::LongLong;         }
505    template <> inline bool MultiType::MT_ValueBase::isType<unsigned long long>()   const { return this->type_ == Type::UnsignedLongLong; }
506    template <> inline bool MultiType::MT_ValueBase::isType<float>()                const { return this->type_ == Type::Float;            }
507    template <> inline bool MultiType::MT_ValueBase::isType<double>()               const { return this->type_ == Type::Double;           }
508    template <> inline bool MultiType::MT_ValueBase::isType<long double>()          const { return this->type_ == Type::LongDouble;       }
509    template <> inline bool MultiType::MT_ValueBase::isType<bool>()                 const { return this->type_ == Type::Bool;             }
510    template <> inline bool MultiType::MT_ValueBase::isType<void*>()                const { return this->type_ == Type::VoidPointer;      }
511    template <> inline bool MultiType::MT_ValueBase::isType<std::string>()          const { return this->type_ == Type::String;           }
512    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector2>()     const { return this->type_ == Type::Vector2;          }
513    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector3>()     const { return this->type_ == Type::Vector3;          }
514    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Vector4>()     const { return this->type_ == Type::Vector4;          }
515    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::ColourValue>() const { return this->type_ == Type::ColourValue;      }
516    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Quaternion>()  const { return this->type_ == Type::Quaternion;       }
517    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Radian>()      const { return this->type_ == Type::Radian;           }
518    template <> inline bool MultiType::MT_ValueBase::isType<orxonox::Degree>()      const { return this->type_ == Type::Degree;           }
519
520    template <> inline bool MultiType::set(const char* value)  { return this->set(std::string(value)); }
521    template <> inline bool MultiType::set(const mbool& value) { return this->set((bool)value); }
522
523    // Spezializations for void
524    template <> inline bool MultiType::isType<void>() const { return this->null(); }
525    template <> inline bool MultiType::convert<void>() { this->reset(); return true; }
526
527    template <> _UtilExport void MultiType::createNewValueContainer(const char& value);
528    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned char& value);
529    template <> _UtilExport void MultiType::createNewValueContainer(const short& value);
530    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned short& value);
531    template <> _UtilExport void MultiType::createNewValueContainer(const int& value);
532    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned int& value);
533    template <> _UtilExport void MultiType::createNewValueContainer(const long& value);
534    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned long& value);
535    template <> _UtilExport void MultiType::createNewValueContainer(const long long& value);
536    template <> _UtilExport void MultiType::createNewValueContainer(const unsigned long long& value);
537    template <> _UtilExport void MultiType::createNewValueContainer(const float& value);
538    template <> _UtilExport void MultiType::createNewValueContainer(const double& value);
539    template <> _UtilExport void MultiType::createNewValueContainer(const bool& value);
540    template <> _UtilExport void MultiType::createNewValueContainer(const long double& value);
541    template <> _UtilExport void MultiType::createNewValueContainer(      void* const& value);
542    template <> _UtilExport void MultiType::createNewValueContainer(const std::string& value);
543    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector2& value);
544    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector3& value);
545    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Vector4& value);
546    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::ColourValue& value);
547    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Quaternion& value);
548    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Radian& value);
549    template <> _UtilExport void MultiType::createNewValueContainer(const orxonox::Degree& value);
550}
551
552#endif /* _MultiType_H__ */
Note: See TracBrowser for help on using the repository browser.