1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        wx/meta/implicitconversion.h
3 // Purpose:     Determine resulting type from implicit conversion
4 // Author:      Vaclav Slavik
5 // Created:     2010-10-22
6 // Copyright:   (c) 2010 Vaclav Slavik
7 // Licence:     wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
9 
10 #ifndef _WX_META_IMPLICITCONVERSION_H_
11 #define _WX_META_IMPLICITCONVERSION_H_
12 
13 #include "wx/defs.h"
14 #include "wx/meta/if.h"
15 
16 // C++ hierarchy of data types is:
17 //
18 //   Long double (highest)
19 //   Double
20 //   Float
21 //   Unsigned long int
22 //   Long int
23 //   Unsigned int
24 //   Int (lowest)
25 //
26 // Types lower in the hierarchy are converted into ones higher up if both are
27 // involved e.g. in arithmetic expressions.
28 
29 namespace wxPrivate
30 {
31 
32 // Helper macro to define a constant inside a template class: it's needed
33 // because MSVC6 doesn't support initializing static integer members but the
34 // usual workaround of using enums instead doesn't work for Borland (at least
35 // in template classes).
36 #ifdef __VISUALC6__
37     #define wxDEFINE_CLASS_INT_CONST(name, value) enum { name = value }
38 #else
39     #define wxDEFINE_CLASS_INT_CONST(name, value) static const int name = value
40 #endif
41 
42 template<typename T>
43 struct TypeHierarchy
44 {
45     // consider unknown types (e.g. objects, pointers) to be of highest
46     // level, always convert to them if they occur
47     wxDEFINE_CLASS_INT_CONST( level, 9999 );
48 };
49 
50 #define WX_TYPE_HIERARCHY_LEVEL(level_num, type)        \
51     template<> struct TypeHierarchy<type>               \
52     {                                                   \
53         wxDEFINE_CLASS_INT_CONST( level, level_num );   \
54     }
55 
56 WX_TYPE_HIERARCHY_LEVEL( 1, char);
57 WX_TYPE_HIERARCHY_LEVEL( 2, unsigned char);
58 WX_TYPE_HIERARCHY_LEVEL( 3, short);
59 WX_TYPE_HIERARCHY_LEVEL( 4, unsigned short);
60 WX_TYPE_HIERARCHY_LEVEL( 5, int);
61 WX_TYPE_HIERARCHY_LEVEL( 6, unsigned int);
62 WX_TYPE_HIERARCHY_LEVEL( 7, long);
63 WX_TYPE_HIERARCHY_LEVEL( 8, unsigned long);
64 #ifdef wxLongLong_t
65 WX_TYPE_HIERARCHY_LEVEL( 9, wxLongLong_t);
66 WX_TYPE_HIERARCHY_LEVEL(10, wxULongLong_t);
67 #endif
68 WX_TYPE_HIERARCHY_LEVEL(11, float);
69 WX_TYPE_HIERARCHY_LEVEL(12, double);
70 WX_TYPE_HIERARCHY_LEVEL(13, long double);
71 
72 #if wxWCHAR_T_IS_REAL_TYPE
73     #if SIZEOF_WCHAR_T == SIZEOF_SHORT
74       template<> struct TypeHierarchy<wchar_t> : public TypeHierarchy<short> {};
75     #elif SIZEOF_WCHAR_T == SIZEOF_INT
76       template<> struct TypeHierarchy<wchar_t> : public TypeHierarchy<int> {};
77     #elif SIZEOF_WCHAR_T == SIZEOF_LONG
78       template<> struct TypeHierarchy<wchar_t> : public TypeHierarchy<long> {};
79     #else
80       #error "weird wchar_t size, please update this code"
81     #endif
82 #endif
83 
84 #undef WX_TYPE_HIERARCHY_LEVEL
85 
86 } // namespace wxPrivate
87 
88 // Helper to determine resulting type of implicit conversion in
89 // an expression with two arithmetic types.
90 template<typename T1, typename T2>
91 struct wxImplicitConversionType
92 {
93     typedef typename wxIf
94             <
95                 // if T2 is "higher" type, convert to it
96                 (int)(wxPrivate::TypeHierarchy<T1>::level) < (int)(wxPrivate::TypeHierarchy<T2>::level),
97                 T2,
98                 // otherwise use T1
99                 T1
100             >::value
101             value;
102 };
103 
104 
105 template<typename T1, typename T2, typename T3>
106 struct wxImplicitConversionType3 : public wxImplicitConversionType<
107                         T1,
108                         typename wxImplicitConversionType<T2,T3>::value>
109 {
110 };
111 
112 #endif // _WX_META_IMPLICITCONVERSION_H_
113