Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/gui/src/util/Convert.h @ 2029

Last change on this file since 2029 was 1664, checked in by rgrieder, 16 years ago
  • Finished CommandLineArgument completely. You can also use SetCommandLineSwitch to define boolean switches.
  • Added StaticConversion to Covert.h (compile time type conversion checking)
  • Fixed a bug in Exception
  • Added getAllStrings() to SubString
  • Property svn:eol-style set to native
File size: 25.0 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 *      Benjamin Grauer
24 *      Fabian 'x3n' Landau
25 *   Co-authors:
26 *      ...
27 */
28
29/*!
30    @file Convert.h
31    @brief Definition and Implementation of the Convert class.
32*/
33
34#ifndef _Convert_H__
35#define _Convert_H__
36
37#include "UtilPrereqs.h"
38
39#include <string>
40#include <sstream>
41
42#include "Math.h"
43#include "SubString.h"
44#include "MultiTypeMath.h"
45#include "String.h"
46
47// disable annoying warning about forcing value to boolean
48#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
49#pragma warning(push)
50#pragma warning(disable:4100 4800)
51#endif
52
53
54//////////
55// MAIN //
56//////////
57
58// Enum to declare the wanted conversion preference in case of equal type-levels
59enum ConversionPreference
60{
61    CP_PreferToType,
62    CP_PreferFromType,
63};
64
65// Helper classes to determine the preferred partial template specialization
66class _ToType_   {};
67class _FromType_ {};
68class _Explicit_ {};
69
70
71// The default convert functions
72template <class FromType, class ToType, class Type>
73struct ConverterSpecialized
74{
75    enum { specialized = false };
76    static bool convert(ToType* output, const FromType& input)
77    { return false; }
78};
79
80
81// The default convert function if both types are the same
82template <class BothTypes>
83struct ConverterSpecialized<BothTypes, BothTypes, _Explicit_>
84{
85    enum { specialized = true };
86    static bool convert(BothTypes* output, const BothTypes& input)
87    { (*output) = input; return true; }
88};
89
90
91// The possible levels
92#define __low__  0 // Everything that is or behaves like a primitive type (an can be converted with a typecast to every other low-level type)
93#define __mid__  1 // Everything that has overloaded << and >> operators to operate on a std::stream
94#define __high__ 2 // Everything that doesn't fullfill the lowerlevel-requirements and therefore needs specialized conversions
95
96// Defines the levels of all types: Default is __high__ so you don't have to define every high-level type
97template <class T> struct ConverterLevel           { enum { level = __high__ }; };
98template <> struct ConverterLevel<std::string>     { enum { level = __mid__ }; };
99template <> struct ConverterLevel<orxonox::Radian> { enum { level = __mid__ }; };
100template <> struct ConverterLevel<orxonox::Degree> { enum { level = __mid__ }; };
101template <> struct ConverterLevel<int>             { enum { level = __low__ }; };
102template <> struct ConverterLevel<unsigned int>    { enum { level = __low__ }; };
103template <> struct ConverterLevel<char>            { enum { level = __low__ }; };
104template <> struct ConverterLevel<unsigned char>   { enum { level = __low__ }; };
105template <> struct ConverterLevel<short>           { enum { level = __low__ }; };
106template <> struct ConverterLevel<unsigned short>  { enum { level = __low__ }; };
107template <> struct ConverterLevel<long>            { enum { level = __low__ }; };
108template <> struct ConverterLevel<unsigned long>   { enum { level = __low__ }; };
109template <> struct ConverterLevel<float>           { enum { level = __low__ }; };
110template <> struct ConverterLevel<double>          { enum { level = __low__ }; };
111template <> struct ConverterLevel<long double>     { enum { level = __low__ }; };
112template <> struct ConverterLevel<bool>            { enum { level = __low__ }; };
113
114
115// Calculates the preference based on the levels of FromType and ToType
116template <int from, int to>
117struct ConverterPreference
118{
119    enum
120    {
121        // The maximum of both levels: element of {0, 1, 2}
122        // max 0: Both types are primitives or have a similar behaviour
123        // max 1: At least one type is not a primitive, but both can be put on a std::stream
124        // max 2: There is at least one generic type that needs specialized conversions
125        max = (from > to) ? from : to,
126
127        // The difference between both levels limited to +-1: element of {-1, 0, 1}
128        // diff -1: The FromType has higher level than the ToType
129        // diff  0: Both types have the same level
130        // diff  1: The ToType has higher level than the FromType
131        diff = ((to - from) > 1) ? 1 : (((to - from) < -1) ? -1 : to - from)
132    };
133};
134
135
136// The default conversion: This usually does nothing
137template <int max, class FromType, class ToType>
138struct ConverterDefault
139{
140    static bool convert(ToType* output, const FromType& input)
141    {
142        return false;
143    }
144};
145// The default conversion for primitives: A typecast (defined over two partial specialized templates to exclude all non-primitive types and classes)    template <int max, class FromType, class ToType>
146template <class FromType, class ToType>
147struct ConverterDefault<0, FromType, ToType>
148{
149    static bool convert(ToType* output, const FromType& input)
150    {
151        (*output) = (ToType)input;
152        return true;
153    }
154};
155
156
157// Converter: Converts input of FromType into output of ToType
158template <int diff, int max, class FromType, class ToType, ConversionPreference pref>
159struct Converter
160{
161    static bool convert(ToType* output, const FromType& input)
162    {
163        return false;
164    }
165};
166// Converter: level{FromType} > level{ToType}
167template <int max, class FromType, class ToType, ConversionPreference pref>
168struct Converter<-1, max, FromType, ToType, pref>
169{   static bool convert(ToType* output, const FromType& input)
170    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _FromType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _FromType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
171// Converter: level{FromType} < level{ToType}
172template <int max, class FromType, class ToType, ConversionPreference pref>
173struct Converter<1, max, FromType, ToType, pref>
174{   static bool convert(ToType* output, const FromType& input)
175    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _ToType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _ToType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
176// Converter: level{FromType} = level{ToType}
177// CP_PreferToType
178template <int max, class FromType, class ToType>
179struct Converter<0, max, FromType, ToType, CP_PreferToType>
180{   static bool convert(ToType* output, const FromType& input)
181    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _ToType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _ToType_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _FromType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _FromType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
182// CP_PreferFromType
183template <int max, class FromType, class ToType>
184struct Converter<0, max, FromType, ToType, CP_PreferFromType>
185{   static bool convert(ToType* output, const FromType& input)
186    { return (ConverterSpecialized<FromType, ToType, _Explicit_>::specialized) ? (ConverterSpecialized<FromType, ToType, _Explicit_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _FromType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _FromType_>::convert(output, input)) : (ConverterSpecialized<FromType, ToType, _ToType_>::specialized) ? (ConverterSpecialized<FromType, ToType, _ToType_>::convert(output, input)) : (ConverterDefault<max, FromType, ToType>::convert(output, input)); } };
187
188
189// Calls the Converter::convertValue function with the correct template type parameters calculated by ConverterPreference
190template <class FromType, class ToType>
191static bool convertValue(ToType* output, const FromType& input, ConversionPreference preference = CP_PreferToType)
192{
193    return (preference == CP_PreferToType) ?
194           Converter<ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::diff,
195                     ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::max,
196                     FromType,
197                     ToType,
198                     CP_PreferToType>::convert(output, input)
199         : Converter<ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::diff,
200                     ConverterPreference<ConverterLevel<FromType>::level, ConverterLevel<ToType>::level>::max,
201                     FromType,
202                     ToType,
203                     CP_PreferFromType>::convert(output, input);
204}
205
206
207//////////////////////
208// HELPER FUNCTIONS //
209//////////////////////
210
211// Helper function: Calls convertValue with and without default value and returns true if the conversion was successful
212template<class FromType, class ToType>
213static bool ConvertValue(ToType* output, const FromType& input, ConversionPreference preference = CP_PreferToType)
214{
215    return convertValue(output, input, preference);
216}
217template<class FromType, class ToType>
218static bool ConvertValue(ToType* output, const FromType& input, const ToType& fallback, ConversionPreference preference = CP_PreferToType)
219{
220    if (convertValue(output, input, preference))
221        return true;
222
223    (*output) = fallback;
224    return false;
225}
226
227// Helper function: Calls convertValue with and without default value and returns the converted value
228template<class FromType, class ToType>
229static ToType getConvertedValue(const FromType& input, ConversionPreference preference = CP_PreferToType)
230{
231    ToType output = ToType();
232    ConvertValue(&output, input, preference);
233    return output;
234}
235template<class FromType, class ToType>
236static ToType getConvertedValue(const FromType& input, const ToType& fallback, ConversionPreference preference = CP_PreferToType)
237{
238    ToType output = fallback;
239    ConvertValue(&output, input, fallback, preference);
240    return output;
241}
242
243
244/////////////////////
245// SPECIALIZATIONS //
246/////////////////////
247
248/////////////
249// SAMPLES //
250/////////////
251/*
252// convert everything to xyz
253template <class FromType>
254struct ConverterSpecialized<FromType, xyz, _ToType_>
255{
256    enum { specialized = true };
257    static bool convert(xyz* output, const FromType& input)
258    { return ...; }
259};
260
261// convert xyz to everything
262template <class ToType>
263struct ConverterSpecialized<xyz, ToType, _FromType_>
264{
265    enum { specialized = true };
266    static bool convert(ToType* output, const xyz& input)
267    { return ...; }
268};
269
270// convert abc to xyz
271template <>
272struct ConverterSpecialized<abc, xyz, _Explicit_>
273{
274    enum { specialized = true };
275    static bool convert(xyz* output, const abc& input)
276    { return ...; }
277};
278*/
279
280////////////
281// STRING //
282////////////
283
284// convert to string
285template <class FromType>
286struct ConverterSpecialized<FromType, std::string, _ToType_>
287{
288    enum { specialized = true };
289    static bool convert(std::string* output, const FromType& input)
290    {
291        std::ostringstream oss;
292        if (oss << input)
293        {
294            (*output) = oss.str();
295            return true;
296        }
297        else
298            return false;
299    }
300};
301
302// convert to string Shortcut
303template <class FromType>
304std::string convertToString(FromType value)
305{
306  return getConvertedValue<FromType, std::string>(value);
307}
308
309// convert from string
310template <class ToType>
311struct ConverterSpecialized<std::string, ToType, _FromType_>
312{
313    enum { specialized = true };
314    static bool convert(ToType* output, const std::string& input)
315    {
316        std::istringstream iss(input);
317        if (iss >> (*output))
318            return true;
319        else
320            return false;
321    }
322};
323
324// convert from string Shortcut
325template <class ToType>
326ToType convertFromString(std::string str)
327{
328  return getConvertedValue<std::string, ToType>(str);
329}
330
331
332////////////////
333// MULTITYPES //
334////////////////
335
336// convert from MultiTypePrimitive
337template <class ToType>
338struct ConverterSpecialized<MultiTypePrimitive, ToType, _FromType_>
339{
340    enum { specialized = true };
341    static bool convert(ToType* output, const MultiTypePrimitive& input)
342    {
343        if (input.getType() == MT_void)
344            return ConvertValue(output, input.getVoid());
345        else if (input.getType() == MT_int)
346            return ConvertValue(output, input.getInt());
347        else if (input.getType() == MT_uint)
348            return ConvertValue(output, input.getUnsignedInt());
349        else if (input.getType() == MT_char)
350            return ConvertValue(output, input.getChar());
351        else if (input.getType() == MT_uchar)
352            return ConvertValue(output, input.getUnsignedChar());
353        else if (input.getType() == MT_short)
354            return ConvertValue(output, input.getShort());
355        else if (input.getType() == MT_ushort)
356            return ConvertValue(output, input.getUnsignedShort());
357        else if (input.getType() == MT_long)
358            return ConvertValue(output, input.getLong());
359        else if (input.getType() == MT_ulong)
360            return ConvertValue(output, input.getUnsignedLong());
361        else if (input.getType() == MT_float)
362            return ConvertValue(output, input.getFloat());
363        else if (input.getType() == MT_double)
364            return ConvertValue(output, input.getDouble());
365        else if (input.getType() == MT_longdouble)
366            return ConvertValue(output, input.getLongDouble());
367        else if (input.getType() == MT_bool)
368            return ConvertValue(output, input.getBool());
369        else
370            return false;
371    }
372};
373
374// convert from MultiTypeString
375template <class ToType>
376struct ConverterSpecialized<MultiTypeString, ToType, _FromType_>
377{
378    enum { specialized = true };
379    static bool convert(ToType* output, const MultiTypeString& input)
380    {
381        if (input.getType() == MT_constchar)
382            return ConvertValue(output, input.getConstChar());
383        else if (input.getType() == MT_string)
384            return ConvertValue(output, input.getString());
385        else
386            return ConvertValue(output, (MultiTypePrimitive)input);
387    }
388};
389
390// convert from MultiTypeMath
391template <class ToType>
392struct ConverterSpecialized<MultiTypeMath, ToType, _FromType_>
393{
394    enum { specialized = true };
395    static bool convert(ToType* output, const MultiTypeMath& input)
396    {
397        if (input.getType() == MT_vector2)
398            return ConvertValue(output, input.getVector2());
399        else if (input.getType() == MT_vector3)
400            return ConvertValue(output, input.getVector3());
401        else if (input.getType() == MT_vector4)
402            return ConvertValue(output, input.getVector4());
403        else if (input.getType() == MT_quaternion)
404            return ConvertValue(output, input.getQuaternion());
405        else if (input.getType() == MT_colourvalue)
406            return ConvertValue(output, input.getColourValue());
407        else if (input.getType() == MT_radian)
408            return ConvertValue(output, input.getRadian());
409        else if (input.getType() == MT_degree)
410            return ConvertValue(output, input.getDegree());
411        else
412            return ConvertValue(output, (MultiTypeString)input);
413    }
414};
415
416
417////////////////////
418// MATH TO STRING //
419////////////////////
420
421// bool to std::string
422template <>
423struct ConverterSpecialized<bool, std::string, _Explicit_>
424{
425    enum { specialized = true };
426    static bool convert(std::string* output, const bool& input)
427    {
428        if (input)
429          *output = "true";
430        else
431          *output = "false";
432        return false;
433    }
434};
435
436// Vector2 to std::string
437template <>
438struct ConverterSpecialized<orxonox::Vector2, std::string, _Explicit_>
439{
440    enum { specialized = true };
441    static bool convert(std::string* output, const orxonox::Vector2& input)
442    {
443        std::ostringstream ostream;
444        if (ostream << input.x << "," << input.y)
445        {
446            (*output) = ostream.str();
447            return true;
448        }
449        return false;
450    }
451};
452
453// Vector3 to std::string
454template <>
455struct ConverterSpecialized<orxonox::Vector3, std::string, _Explicit_>
456{
457    enum { specialized = true };
458    static bool convert(std::string* output, const orxonox::Vector3& input)
459    {
460        std::ostringstream ostream;
461        if (ostream << input.x << "," << input.y << "," << input.z)
462        {
463            (*output) = ostream.str();
464            return true;
465        }
466        return false;
467    }
468};
469
470// Vector4 to std::string
471template <>
472struct ConverterSpecialized<orxonox::Vector4, std::string, _Explicit_>
473{
474    enum { specialized = true };
475    static bool convert(std::string* output, const orxonox::Vector4& input)
476    {
477        std::ostringstream ostream;
478        if (ostream << input.x << "," << input.y << "," << input.z << "," << input.w)
479        {
480            (*output) = ostream.str();
481            return true;
482        }
483        return false;
484    }
485};
486
487// Quaternion to std::string
488template <>
489struct ConverterSpecialized<orxonox::Quaternion, std::string, _Explicit_>
490{
491    enum { specialized = true };
492    static bool convert(std::string* output, const orxonox::Quaternion& input)
493    {
494        std::ostringstream ostream;
495        if (ostream << input.w << "," << input.x << "," << input.y << "," << input.z)
496        {
497            (*output) = ostream.str();
498            return true;
499        }
500        return false;
501    }
502};
503
504// ColourValue to std::string
505template <>
506struct ConverterSpecialized<orxonox::ColourValue, std::string, _Explicit_>
507{
508    enum { specialized = true };
509    static bool convert(std::string* output, const orxonox::ColourValue& input)
510    {
511        std::ostringstream ostream;
512        if (ostream << input.r << "," << input.g << "," << input.b << "," << input.a)
513        {
514            (*output) = ostream.str();
515            return true;
516        }
517        return false;
518    }
519};
520
521
522////////////////////
523// STRING TO MATH //
524////////////////////
525
526// std::string to bool
527template <>
528struct ConverterSpecialized<std::string, bool, _Explicit_>
529{
530    enum { specialized = true };
531    static bool convert(bool* output, const std::string& input)
532    {
533        std::string stripped = getLowercase(removeTrailingWhitespaces(input));
534        if (stripped == "true" || stripped == "on" || stripped == "yes")
535        {
536          *output = true;
537          return true;
538        }
539        else if (stripped == "false" || stripped == "off" || stripped == "no")
540        {
541          *output = false;
542          return true;
543        }
544
545        std::istringstream iss(input);
546        if (iss >> (*output))
547            return true;
548        else
549            return false;
550    }
551};
552
553// std::string to Vector2
554template <>
555struct ConverterSpecialized<std::string, orxonox::Vector2, _Explicit_>
556{
557    enum { specialized = true };
558    static bool convert(orxonox::Vector2* output, const std::string& input)
559    {
560        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
561        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
562
563        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
564        if (tokens.size() >= 2)
565        {
566            if (!ConvertValue(&(output->x), tokens[0]))
567                return false;
568            if (!ConvertValue(&(output->y), tokens[1]))
569                return false;
570
571            return true;
572        }
573        return false;
574    }
575};
576
577// std::string to Vector3
578template <>
579struct ConverterSpecialized<std::string, orxonox::Vector3, _Explicit_>
580{
581    enum { specialized = true };
582    static bool convert(orxonox::Vector3* output, const std::string& input)
583    {
584        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
585        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
586
587        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
588        if (tokens.size() >= 3)
589        {
590            if (!ConvertValue(&(output->x), tokens[0]))
591                return false;
592            if (!ConvertValue(&(output->y), tokens[1]))
593                return false;
594            if (!ConvertValue(&(output->z), tokens[2]))
595                return false;
596
597            return true;
598        }
599        return false;
600    }
601};
602
603// std::string to Vector4
604template <>
605struct ConverterSpecialized<std::string, orxonox::Vector4, _Explicit_>
606{
607    enum { specialized = true };
608    static bool convert(orxonox::Vector4* output, const std::string& input)
609    {
610        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
611        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
612
613        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
614        if (tokens.size() >= 4)
615        {
616            if (!ConvertValue(&(output->x), tokens[0]))
617                return false;
618            if (!ConvertValue(&(output->y), tokens[1]))
619                return false;
620            if (!ConvertValue(&(output->z), tokens[2]))
621                return false;
622            if (!ConvertValue(&(output->w), tokens[3]))
623                return false;
624
625            return true;
626        }
627        return false;
628    }
629};
630
631// std::string to Quaternion
632template <>
633struct ConverterSpecialized<std::string, orxonox::Quaternion, _Explicit_>
634{
635    enum { specialized = true };
636    static bool convert(orxonox::Quaternion* output, const std::string& input)
637    {
638        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
639        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
640
641        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
642        if (tokens.size() >= 4)
643        {
644            if (!ConvertValue(&(output->w), tokens[0]))
645                return false;
646            if (!ConvertValue(&(output->x), tokens[1]))
647                return false;
648            if (!ConvertValue(&(output->y), tokens[2]))
649                return false;
650            if (!ConvertValue(&(output->z), tokens[3]))
651                return false;
652
653            return true;
654        }
655        return false;
656    }
657};
658
659// std::string to ColourValue
660template <>
661struct ConverterSpecialized<std::string, orxonox::ColourValue, _Explicit_>
662{
663    enum { specialized = true };
664    static bool convert(orxonox::ColourValue* output, const std::string& input)
665    {
666        unsigned int opening_parenthesis, closing_parenthesis = input.find(')');
667        if ((opening_parenthesis = input.find('(')) == std::string::npos) { opening_parenthesis = 0; } else { opening_parenthesis++; }
668
669        SubString tokens(input.substr(opening_parenthesis, closing_parenthesis - opening_parenthesis), ",", SubString::WhiteSpaces, false, '\\', true, '"', true, '\0', '\0', true, '\0');
670        if (tokens.size() >= 3)
671        {
672            if (!ConvertValue(&(output->r), tokens[0]))
673                return false;
674            if (!ConvertValue(&(output->g), tokens[1]))
675                return false;
676            if (!ConvertValue(&(output->b), tokens[2]))
677                return false;
678            if (tokens.size() >= 4)
679            {
680                if (!ConvertValue(&(output->a), tokens[3]))
681                    return false;
682            }
683            else
684                output->a = 1.0;
685
686            return true;
687        }
688        return false;
689    }
690};
691
692
693///////////////////////////
694// Static type detection //
695///////////////////////////
696
697/**
698    Template class that determines whether type T converts implicitly to type U.
699@note
700    This allows to detect type conversion at compile time.
701    From 'Modern C++ Design' (Alexandrescu 2001).
702*/
703template <class T, class U>
704class StaticConversion
705{
706    class Small { char dummy[1]; };
707    class Big   { char dummy[1024]; };
708    static Small Test(U);
709    static Big   Test(...);
710    static T MakeT();
711public:
712    enum { exists = sizeof(Test(MakeT())) == sizeof(Small) };
713};
714
715#if ORXONOX_COMPILER == ORXONOX_COMPILER_MSVC
716#pragma warning(pop)
717#endif
718
719#endif /* _Convert_H__ */
Note: See TracBrowser for help on using the repository browser.