git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
C++: nicer casts
commit6e277f43b4f1d0c5991b10dea37e2e7cf7476f52 authorAndy Arvanitis <andyarvanitis@gmail.com> dateSun 24 Apr 2016, 17:38 (11 years ago) parentb997d65
3 files changed+73−123
pcc/include/purescript.cc+20−64 pcc/include/purescript.hh+52−58 src/Language/PureScript/Pretty/Cpp.hs+1−1
pcc/include/purescript.cc+20−64
@@ -22,59 +22,6 @@ namespace PureScript {
2222 assert(variant.type == TYPE); \
2323 return INDIRECTION(variant.ACCESSOR); \
2424
25−template <typename T>
26−auto any::cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type {
27− RETURN_VALUE(Type::Integer, i,)
28−}
29−template auto any::cast<long>() const -> long;
30−
31−template <typename T>
32−auto any::cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type {
33− RETURN_VALUE(Type::Double, d,)
34−}
35−template auto any::cast<double>() const -> double;
36−
37−template <typename T>
38−auto any::cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type {
39− RETURN_VALUE(Type::Character, c,)
40−}
41−template auto any::cast<char>() const -> char;
42−
43−template <typename T>
44−auto any::cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type {
45− RETURN_VALUE(Type::Boolean, b,)
46−}
47−template auto any::cast<bool>() const -> bool;
48−
49−template <typename T>
50−auto any::cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type {
51− const any& variant = unthunkVariant(*this);
52− if (variant.type == Type::StringLiteral) {
53− return variant.r;
54− }
55− assert(variant.type == Type::String);
56− return variant.s->c_str();
57−}
58−template auto any::cast<string>() const -> string;
59−
60−template <typename T>
61−auto any::cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type {
62− RETURN_VALUE(Type::Map, m, *)
63−}
64−template auto any::cast<any::map>() const -> const map&;
65−
66−template <typename T>
67−auto any::cast() const -> typename std::enable_if<std::is_same<T, data>::value, const T&>::type {
68− RETURN_VALUE(Type::Data, v, *)
69−}
70−template auto any::cast<any::data>() const -> const data&;
71−
72−template <typename T>
73−auto any::cast() const -> typename std::enable_if<std::is_same<T, array>::value, const T&>::type {
74− RETURN_VALUE(Type::Array, a, *)
75−}
76−template auto any::cast<any::array>() const -> const array&;
77−
7825auto any::operator()(const any& arg) const -> any {
7926 const any& variant = unthunkVariant(*this);
8027 if (variant.type == Type::Closure) {
@@ -96,31 +43,40 @@ auto any::operator()() const -> any {
9643}
9744
9845any::operator long() const {
99− return cast<long>();
46+ RETURN_VALUE(Type::Integer, i,)
10047}
10148
10249any::operator double() const {
103− return cast<double>();
50+ RETURN_VALUE(Type::Double, d,)
10451}
10552
10653any::operator bool() const {
107− return cast<bool>();
54+ RETURN_VALUE(Type::Boolean, b,)
55+}
56+
57+any::operator char() const {
58+ RETURN_VALUE(Type::Character, c,)
10859}
10960
110−any::operator string() const {
111− return cast<string>();
61+any::operator cstring() const {
62+ const any& variant = unthunkVariant(*this);
63+ if (variant.type == Type::StringLiteral) {
64+ return variant.r;
65+ }
66+ assert(variant.type == Type::String);
67+ return variant.s->c_str();
11268}
11369
11470any::operator const map&() const {
115− return cast<map>();
71+ RETURN_VALUE(Type::Map, m, *)
11672}
11773
11874any::operator const data&() const {
119− return cast<data>();
75+ RETURN_VALUE(Type::Data, v, *)
12076}
12177
12278any::operator const array&() const {
123− return cast<array>();
79+ RETURN_VALUE(Type::Array, a, *)
12480}
12581
12682auto any::extractPointer() const -> void* {
@@ -162,7 +118,7 @@ auto any::operator[](const size_t rhs) const -> const any& {
162118auto any::operator[](const any& rhs) const -> const any& {
163119 const any& variant = unthunkVariant(*this);
164120 assert(variant.type == Type::Array);
165− return (*variant.a)[rhs.cast<long>()];
121+ return (*variant.a)[cast<long>(rhs)];
166122}
167123
168124auto any::contains(const char key[]) const -> bool {
@@ -207,10 +163,10 @@ auto any::contains(const char key[]) const -> bool {
207163
208164#define DEFINE_CSTR_COMPARISON_OPERATOR(op) \
209165 auto operator op (const any& lhs, const char * rhs) -> bool { \
210− return strcmp(lhs.cast<string>(), rhs) op 0; \
166+ return strcmp(cast<cstring>(lhs), rhs) op 0; \
211167 } \
212168 auto operator op (const char * lhs, const any& rhs) -> bool { \
213− return strcmp(lhs, rhs.cast<string>()) op 0; \
169+ return strcmp(lhs, cast<cstring>(rhs)) op 0; \
214170 }
215171
216172#define DEFINE_COMPARISON_OPERATOR(op) \
pcc/include/purescript.hh+52−58
@@ -34,34 +34,9 @@
3434#include <stdexcept>
3535#include <iso646.h> // mostly for MS Visual Studio compiler
3636
37−#define DEFINE_OPERATOR(op, ty, rty) \
38− inline friend auto operator op (const any& lhs, ty rhs) -> rty { \
39− return lhs.cast<ty>() op rhs; \
40− } \
41− inline friend auto operator op (ty lhs, const any& rhs) -> rty { \
42− return lhs op rhs.cast<ty>(); \
43− } \
44−
45−#define DEFINE_INT_OPERATOR(op, rty) \
46− inline friend auto operator op (const any& lhs, int rhs) -> rty { \
47− return lhs.cast<long>() op (long)rhs; \
48− } \
49− inline friend auto operator op (int lhs, const any& rhs) -> rty { \
50− return (long)lhs op rhs.cast<long>(); \
51− }
52−
53−#define DECLARE_COMPARISON_OPERATOR(op) \
54− friend auto operator op (const any&, const any&) -> bool; \
55− DEFINE_OPERATOR(op, long, bool) \
56− DEFINE_OPERATOR(op, double, bool) \
57− DEFINE_OPERATOR(op, char, bool) \
58− DEFINE_INT_OPERATOR(op, bool) \
59− friend auto operator op (const any&, const char * const) -> bool; \
60− friend auto operator op (const char * const, const any&) -> bool;
61−
6237namespace PureScript {
6338
64−using string = const char *;
39+using cstring = const char *;
6540using nullptr_t = std::nullptr_t;
6641
6742// Workaround for missing C++11 version in gcc
@@ -158,7 +133,7 @@ class any {
158133 mutable double d;
159134 mutable char c;
160135 mutable bool b;
161− mutable string r;
136+ mutable cstring r;
162137 mutable fn f;
163138 mutable shared<std::string> s;
164139 mutable shared<map> m;
@@ -280,35 +255,6 @@ class any {
280255 destruct();
281256 }
282257
283− template <typename T>
284− auto cast() const -> typename std::enable_if<std::is_same<T, long>::value, T>::type;
285−
286− template <typename T>
287− auto cast() const -> typename std::enable_if<std::is_same<T, double>::value, T>::type;
288−
289− template <typename T>
290− auto cast() const -> typename std::enable_if<std::is_same<T, char>::value, T>::type;
291−
292− template <typename T>
293− auto cast() const -> typename std::enable_if<std::is_same<T, bool>::value, T>::type;
294−
295− template <typename T>
296− auto cast() const -> typename std::enable_if<std::is_same<T, string>::value, T>::type;
297−
298− template <typename T>
299− auto cast() const -> typename std::enable_if<std::is_same<T, map>::value, const T&>::type;
300−
301− template <typename T>
302− auto cast() const -> typename std::enable_if<std::is_same<T, data>::value, const T&>::type;
303−
304− template <typename T>
305− auto cast() const -> typename std::enable_if<std::is_same<T, array>::value, const T&>::type;
306−
307− template <typename T>
308− auto cast() const -> typename std::enable_if<std::is_assignable<shared<void>,T>::value, typename T::element_type*>::type {
309− return static_cast<typename T::element_type*>(extractPointer());
310− }
311−
312258 auto operator()(const any&) const -> any;
313259 auto operator()(const as_thunk) const -> const any&;
314260 auto operator()() const -> any;
@@ -316,8 +262,8 @@ class any {
316262 operator long() const;
317263 operator double() const;
318264 operator bool() const;
319−
320− operator string() const;
265+ operator char() const;
266+ operator cstring() const;
321267 operator const map&() const;
322268 operator const data&() const;
323269 operator const array&() const;
@@ -332,6 +278,31 @@ class any {
332278
333279 static auto unthunkVariant(const any&) -> const any&;
334280
281+ #define DEFINE_OPERATOR(op, ty, rty) \
282+ inline friend auto operator op (const any& lhs, ty rhs) -> rty { \
283+ return (ty)lhs op rhs; \
284+ } \
285+ inline friend auto operator op (ty lhs, const any& rhs) -> rty { \
286+ return lhs op (ty)rhs; \
287+ } \
288+
289+ #define DEFINE_INT_OPERATOR(op, rty) \
290+ inline friend auto operator op (const any& lhs, int rhs) -> rty { \
291+ return (long)lhs op (long)rhs; \
292+ } \
293+ inline friend auto operator op (int lhs, const any& rhs) -> rty { \
294+ return (long)lhs op (long)rhs; \
295+ }
296+
297+ #define DECLARE_COMPARISON_OPERATOR(op) \
298+ friend auto operator op (const any&, const any&) -> bool; \
299+ DEFINE_OPERATOR(op, long, bool) \
300+ DEFINE_OPERATOR(op, double, bool) \
301+ DEFINE_OPERATOR(op, char, bool) \
302+ DEFINE_INT_OPERATOR(op, bool) \
303+ friend auto operator op (const any&, const char * const) -> bool; \
304+ friend auto operator op (const char * const, const any&) -> bool;
305+
335306 DECLARE_COMPARISON_OPERATOR(==)
336307 DECLARE_COMPARISON_OPERATOR(!=)
337308 DECLARE_COMPARISON_OPERATOR(<)
@@ -378,6 +349,29 @@ class any {
378349 friend auto operator-(const any&) -> any; // unary negate
379350};
380351
352+template <typename T>
353+inline auto cast(const any& a) ->
354+ typename std::enable_if<std::is_arithmetic<T>::value ||
355+ std::is_same<T,cstring>::value, T>::type {
356+ return a;
357+}
358+
359+template <typename T>
360+inline auto cast(const any& a) ->
361+ typename std::enable_if<std::is_same<T, any::map>::value ||
362+ std::is_same<T, any::data>::value ||
363+ std::is_same<T, any::array>::value, const T&>::type {
364+ return a;
365+}
366+
367+template <typename T, typename = typename std::enable_if<std::is_class<T>::value>::type>
368+inline auto cast(const any& a) ->
369+ typename std::enable_if<!std::is_same<T, any::map>::value &&
370+ !std::is_same<T, any::data>::value &&
371+ !std::is_same<T, any::array>::value, T&>::type {
372+ return *static_cast<T*>(a.extractPointer());
373+}
374+
381375} // namespace PureScript
382376
383377#undef DEFINE_OPERATOR
src/Language/PureScript/Pretty/Cpp.hs+1−1
@@ -229,7 +229,7 @@ literals = mkPattern' match
229229 CppNumericLiteral {} -> vstr
230230 CppStringLiteral {} -> vstr
231231 CppBooleanLiteral {} -> vstr
232− _ -> val' ++ ".cast" ++ angles (runType typ) ++ parens []
232+ _ -> "cast" ++ angles (runType typ) ++ parens val'
233233 where
234234 vstr = prettyPrintCpp1 val
235235 val' | '(' `elem` vstr || '[' `elem` vstr = parens vstr