Lumiera 0.pre.04~rc.1
»edit your freedom«
Loading...
Searching...
No Matches
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
42#ifndef UTIL_ACCESS_CASTED_H
43#define UTIL_ACCESS_CASTED_H
44
45#include "lib/error.hpp"
46
47#include <type_traits>
48#include <utility>
49
50
51
52namespace util {
53
54 namespace error = lumiera::error;
55
56 namespace { // implementation helper traits....
57
58 using std::remove_pointer;
59 using std::remove_reference;
60
61
62 template <typename T>
63 using PlainType = typename remove_pointer<
64 typename remove_reference<T>::type>::type;
65
66 template <typename T>
67 struct has_RTTI
68 {
69 static constexpr bool value = std::is_polymorphic<PlainType<T>>::value;
70 };
71
72 template <typename SRC, typename TAR>
74 {
75 static constexpr bool value = std::is_base_of<PlainType<SRC>, PlainType<TAR>>::value
76 && ( ( std::is_pointer<typename remove_reference<SRC>::type>::value
77 && std::is_pointer<typename remove_reference<TAR>::type>::value
78 )
79 ||( !std::is_pointer<typename remove_reference<SRC>::type>::value
80 && !std::is_pointer<typename remove_reference<TAR>::type>::value
81 ));
82 };
83
84 template <typename SRC, typename TAR>
86 {
87 static constexpr bool value = !std::is_convertible<SRC,TAR>::value
91 };
92
93 template <typename SRC, typename TAR>
95 : std::is_convertible<SRC,TAR>
96 { };
97
98 template <typename SRC, typename TAR>
100 {
101 static constexpr bool value = !std::is_rvalue_reference<SRC>::value // considered dangerous
102 && !std::is_pointer<typename remove_reference<SRC>::type>::value
103 && std::is_pointer<typename remove_reference<TAR>::type>::value;
104 };
105
106 template <typename SRC, typename TAR>
108 {
109 static constexpr bool value = !std::is_pointer<typename remove_reference<TAR>::type>::value
110 && std::is_pointer<typename remove_reference<SRC>::type>::value;
111 };
112
113
114 template <typename SRC, typename TAR>
116 : std::enable_if< can_use_dynamic_downcast<SRC,TAR>::value, TAR>
117 { };
118
119 template <typename SRC, typename TAR>
121 : std::enable_if< can_use_conversion<SRC,TAR>::value, TAR>
122 { };
123
124 template <typename SRC, typename TAR>
126 : std::enable_if< can_take_address<SRC,TAR>::value, TAR>
127 { };
128
129 template <typename SRC, typename TAR>
131 : std::enable_if< can_dereference<SRC,TAR>::value, TAR>
132 { };
133
134 }//(End)helper traits
135
136
137
138
143 template<typename TAR>
145 {
146 typedef TAR Ret;
147
148
149 template<typename SRC>
150 static typename if_can_use_dynamic_downcast<SRC&&,TAR>::type
151 access (SRC&& elem)
152 {
153 try
154 {
155 return dynamic_cast<TAR> (std::forward<SRC>(elem));
156 }
157 catch (std::bad_cast& castError)
158 {
159 throw error::Invalid(castError
160 ,"AccessCasted: not the expected runtime type; downcast failed"
161 ,error::LUMIERA_ERROR_WRONG_TYPE);
162 }
163 }
164
165
166 template<typename SRC>
167 static typename if_can_use_conversion<SRC&&,TAR>::type
168 access (SRC&& elem)
169 {
170 return std::forward<SRC> (elem);
171 }
172
173
174 template<typename SRC>
175 static typename if_can_take_address<SRC&&,TAR>::type
176 access (SRC&& elem)
177 {
178 return AccessCasted<TAR>::access (&elem);
179 }
180
181
182 template<typename SRC>
183 static typename if_can_dereference<SRC&&,TAR>::type
184 access (SRC&& elem)
185 {
186 if (!elem)
187 throw error::Invalid("AccessCasted: attempt to build a value or reference from a NULL pointer"
188 ,error::LUMIERA_ERROR_BOTTOM_VALUE);
189
190 return AccessCasted<TAR>::access (*elem);
191 }
192
193
195 static TAR
196 access (...)
197 {
198 // NOTE: if you see this assertion failure, none of the above predicates were true.
199 // Chances are that you requested a conversion that is logically impossible or dangerous,
200 // like e.g. taking a reference from an anonymous value parameter
201 static_assert (!sizeof(TAR), "AccessCasted: No valid conversion or cast supported for these types.");
202 throw error::Invalid("impossible or unsafe type conversion requested");
203 }
204 };
205
206
207
208} // namespace util
209#endif
Lumiera error handling (C++ interface).
LumieraError< LERR_(INVALID)> Invalid
Definition error.hpp:211
typename remove_pointer< typename remove_reference< T >::type >::type PlainType
Helper template to access a given value, possibly converted or casted in a safe way.
static if_can_use_conversion< SRC &&, TAR >::type access(SRC &&elem)
static if_can_use_dynamic_downcast< SRC &&, TAR >::type access(SRC &&elem)
static if_can_dereference< SRC &&, TAR >::type access(SRC &&elem)
static TAR access(...)
catch-all to signal failure of conversion
static if_can_take_address< SRC &&, TAR >::type access(SRC &&elem)