Lumiera  0.pre.03
»edityourfreedom«
access-casted-o.hpp
Go to the documentation of this file.
1 /*
2  ACCESS-CASTED.hpp - util template to access a value using conversion or cast as appropriate
3 
4  Copyright (C) Lumiera.org
5  2008, Hermann Vosseler <Ichthyostega@web.de>
6 
7  This program is free software; you can redistribute it and/or
8  modify it under the terms of the GNU General Public License as
9  published by the Free Software Foundation; either version 2 of
10  the License, or (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program; if not, write to the Free Software
19  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 */
22 
23 
45 #ifndef UTIL_ACCESS_CASTED_O_H
46 #define UTIL_ACCESS_CASTED_O_H
47 
48 #include <type_traits>
49 
50 
51 
52 namespace util {
53 
54  namespace {
55  using std::remove_pointer;
56  using std::remove_reference;
57  using std::is_convertible;
58  using std::is_polymorphic;
59  using std::is_base_of;
60 
61 
62  template <typename SRC, typename TAR>
63  struct can_cast : std::false_type {};
64 
65  template <typename SRC, typename TAR>
66  struct can_cast<SRC*,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
67 
68  template <typename SRC, typename TAR>
69  struct can_cast<SRC*&,TAR*> { enum { value = is_base_of<SRC,TAR>::value };};
70 
71  template <typename SRC, typename TAR>
72  struct can_cast<SRC&,TAR&> { enum { value = is_base_of<SRC,TAR>::value };};
73 
74 
75  template <typename T>
76  struct hasRTTI
77  {
78  typedef typename remove_pointer<
79  typename remove_reference<T>::type>::type TPlain;
80 
81  enum { value = is_polymorphic<TPlain>::value };
82  };
83 
84  template <typename SRC, typename TAR>
85  struct use_dynamic_downcast
86  {
87  enum { value = can_cast<SRC,TAR>::value
88  && hasRTTI<SRC>::value
89  && hasRTTI<TAR>::value
90  };
91  };
92 
93  template <typename SRC, typename TAR>
94  struct use_static_downcast
95  {
96  enum { value = can_cast<SRC,TAR>::value
97  && ( !hasRTTI<SRC>::value
98  || !hasRTTI<TAR>::value
99  )
100  };
101  };
102 
103  template <typename SRC, typename TAR>
104  struct use_conversion
105  {
106  enum { value = is_convertible<SRC,TAR>::value
107  && !( use_static_downcast<SRC,TAR>::value
108  ||use_dynamic_downcast<SRC,TAR>::value
109  )
110  };
111  };
112 
113 
114 
115  template<typename X>
116  struct EmptyVal
117  {
118  static X create() { return X(); }
119  };
120  template<typename X>
121  struct EmptyVal<X*&>
122  {
123  static X*& create() { static X* nullP(0); return nullP; }
124  };
125 
126  }
127 
128 
129 
130 
131  template<typename RET>
133  {
134  typedef RET Ret;
135 
136  static RET access (...) { return ifEmpty(); }
137  static RET ifEmpty () { return EmptyVal<RET>::create(); }
138  };
139 
140  template<typename TAR>
142  {
144 
145  template<typename ELM>
146  static typename std::enable_if< use_dynamic_downcast<ELM&,TAR>::value,
147  TAR >::type
148  access (ELM& elem)
149  {
150  return dynamic_cast<TAR> (elem);
151  }
152 
153  template<typename ELM>
154  static typename std::enable_if< use_static_downcast<ELM&,TAR>::value,
155  TAR >::type
156  access (ELM& elem)
157  {
158  return static_cast<TAR> (elem);
159  }
160 
161  template<typename ELM>
162  static typename std::enable_if< use_conversion<ELM&,TAR>::value,
163  TAR >::type
164  access (ELM& elem)
165  {
166  return elem;
167  }
168  };
169 
170 
171 } // namespace util
172 #endif
static std::enable_if< use_conversion< ELM &, TAR >::value, TAR >::type access(ELM &elem)
static std::enable_if< use_static_downcast< ELM &, TAR >::value, TAR >::type access(ELM &elem)
static RET access(...)
static std::enable_if< use_dynamic_downcast< ELM &, TAR >::value, TAR >::type access(ELM &elem)