Lumiera  0.pre.03
»edit your freedom«
access-casted.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)
5  2008, 2015 Hermann Vosseler <Ichthyostega@web.de>
6 
7   **Lumiera** is free software; you can redistribute it and/or modify it
8   under the terms of the GNU General Public License as published by the
9   Free Software Foundation; either version 2 of the License, or (at your
10   option) any later version. See the file COPYING for further details.
11 
12 */
13 
14 
41 #ifndef UTIL_ACCESS_CASTED_H
42 #define UTIL_ACCESS_CASTED_H
43 
44 #include "lib/error.hpp"
45 
46 #include <type_traits>
47 #include <utility>
48 
49 
50 
51 namespace util {
52 
53  namespace error = lumiera::error;
54 
55  namespace { // implementation helper traits....
56 
57  using std::remove_pointer;
58  using std::remove_reference;
59 
60 
61  template <typename T>
62  using PlainType = typename remove_pointer<
63  typename remove_reference<T>::type>::type;
64 
65  template <typename T>
66  struct has_RTTI
67  {
68  static constexpr bool value = std::is_polymorphic<PlainType<T>>::value;
69  };
70 
71  template <typename SRC, typename TAR>
72  struct can_downcast
73  {
74  static constexpr bool value = std::is_base_of<PlainType<SRC>, PlainType<TAR>>::value
75  && ( ( std::is_pointer<typename remove_reference<SRC>::type>::value
76  && std::is_pointer<typename remove_reference<TAR>::type>::value
77  )
78  ||( !std::is_pointer<typename remove_reference<SRC>::type>::value
79  && !std::is_pointer<typename remove_reference<TAR>::type>::value
80  ));
81  };
82 
83  template <typename SRC, typename TAR>
85  {
86  static constexpr bool value = !std::is_convertible<SRC,TAR>::value
90  };
91 
92  template <typename SRC, typename TAR>
94  : std::is_convertible<SRC,TAR>
95  { };
96 
97  template <typename SRC, typename TAR>
99  {
100  static constexpr bool value = !std::is_rvalue_reference<SRC>::value // considered dangerous
101  && !std::is_pointer<typename remove_reference<SRC>::type>::value
102  && std::is_pointer<typename remove_reference<TAR>::type>::value;
103  };
104 
105  template <typename SRC, typename TAR>
107  {
108  static constexpr bool value = !std::is_pointer<typename remove_reference<TAR>::type>::value
109  && std::is_pointer<typename remove_reference<SRC>::type>::value;
110  };
111 
112 
113  template <typename SRC, typename TAR>
115  : std::enable_if< can_use_dynamic_downcast<SRC,TAR>::value, TAR>
116  { };
117 
118  template <typename SRC, typename TAR>
120  : std::enable_if< can_use_conversion<SRC,TAR>::value, TAR>
121  { };
122 
123  template <typename SRC, typename TAR>
125  : std::enable_if< can_take_address<SRC,TAR>::value, TAR>
126  { };
127 
128  template <typename SRC, typename TAR>
130  : std::enable_if< can_dereference<SRC,TAR>::value, TAR>
131  { };
132 
133  }//(End)helper traits
134 
135 
136 
137 
142  template<typename TAR>
144  {
145  typedef TAR Ret;
146 
147 
148  template<typename SRC>
149  static typename if_can_use_dynamic_downcast<SRC&&,TAR>::type
150  access (SRC&& elem)
151  {
152  try
153  {
154  return dynamic_cast<TAR> (std::forward<SRC>(elem));
155  }
156  catch (std::bad_cast& castError)
157  {
158  throw error::Invalid(castError
159  ,"AccessCasted: not the expected runtime type; downcast failed"
160  ,error::LUMIERA_ERROR_WRONG_TYPE);
161  }
162  }
163 
164 
165  template<typename SRC>
166  static typename if_can_use_conversion<SRC&&,TAR>::type
167  access (SRC&& elem)
168  {
169  return std::forward<SRC> (elem);
170  }
171 
172 
173  template<typename SRC>
174  static typename if_can_take_address<SRC&&,TAR>::type
175  access (SRC&& elem)
176  {
177  return AccessCasted<TAR>::access (&elem);
178  }
179 
180 
181  template<typename SRC>
182  static typename if_can_dereference<SRC&&,TAR>::type
183  access (SRC&& elem)
184  {
185  if (!elem)
186  throw error::Invalid("AccessCasted: attempt to build a value or reference from a NULL pointer"
187  ,error::LUMIERA_ERROR_BOTTOM_VALUE);
188 
189  return AccessCasted<TAR>::access (*elem);
190  }
191 
192 
194  static TAR
195  access (...)
196  {
197  // NOTE: if you see this assertion failure, none of the above predicates were true.
198  // Chances are that you requested a conversion that is logically impossible or dangerous,
199  // like e.g. taking a reference from an anonymous value parameter
200  static_assert (!sizeof(TAR), "AccessCasted: No valid conversion or cast supported for these types.");
201  throw error::Invalid("impossible or unsafe type conversion requested");
202  }
203  };
204 
205 
206 
207 } // namespace util
208 #endif
Helper template to access a given value, possibly converted or casted in a safe way.
static TAR access(...)
catch-all to signal failure of conversion
Derived specific exceptions within Lumiera&#39;s exception hierarchy.
Definition: error.hpp:190
Lumiera error handling (C++ interface).