Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/cpp11_v2/src/libraries/util/MultiType.h @ 11002

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

MultiType now supports strongly typed enum classes. Their values are cast to the underlying type.
MultiType now also uses additional static_asserts to ensure that it is only used with supported values.

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