The check to see if an item was already on the heap was randomly hitting.
[jitcs.git] / include / jitcs_adt_ref.h
blob1ea25a21b1d107c00aef6faaf22d78c129246628
1 //===-- jitcs_adt_ref.h - pointer helper type -------------------*- C++ -*-===//
2 //
3 // This file contains two pointer types. The first, Ref, represents a single
4 // pointer, which CANNOT be NULL. Data access is possible thru the use of
5 // the -> operator. The second type, RefOrNull, represents a pointer which
6 // CAN be NULL. Access to the pointed-to data by usage of the method
7 // removeNullType. (The principle of this is taken from the language Ceylon
8 // which, according to my understanding, handles null pointer quite nicely.)
9 //
10 //===----------------------------------------------------------------------===//
12 #ifndef _JITCS_ADT_REF_H_
13 #define _JITCS_ADT_REF_H_
15 #include <assert.h>
16 #include <type_traits>
18 namespace jitcs {
19 enum {
20 REF_Any = 0,
21 REF_Nullable = 1,
22 REF_Const = 2,
25 template <bool b, typename = typename std::enable_if<b,int>::type>
26 void guarantee(const char *) {}
28 // _Ref is an attributed pointer type.
29 // Currently it supports the const-attribute of its data, and
30 // the nonnull-attribute of the pointer.
32 template <typename T, unsigned FLAGS>
33 struct _Ref {
34 typedef typename std::add_const<T>::type CType;
35 typedef T NCType;
36 static const bool IsConstRef = (FLAGS & REF_Const) != 0;
37 typedef typename std::conditional<IsConstRef, CType, NCType>::type Type;
38 typedef Type* PtrType;
39 typedef Type& RefType;
41 _Ref() {
42 guarantee<(FLAGS & REF_Nullable) != 0>
43 ("Default constructor only for nullable refs");
44 _ptr = nullptr;
45 _isValid = false;
47 _Ref(const _Ref&) = default;
48 _Ref& operator = (const _Ref&) = default;
49 PtrType ptr() {
50 assert(_isValid);
51 return _ptr;
53 PtrType operator ->() {
54 guarantee<(FLAGS & REF_Nullable) == 0>
55 ("dereferencing only for non-nullable refs, remove nullable first");
56 return ptr();
58 RefType operator *() {
59 guarantee<(FLAGS & REF_Nullable) == 0>
60 ("dereferencing only for non-nullable refs, remove nullable first");
61 return *ptr();
64 template <typename T2, unsigned FLAGS2>
65 _Ref(_Ref<T2, FLAGS2> o) {
66 static_assert((~FLAGS & FLAGS2) == 0, "incompatible _Ref flags");
67 //static_assert(std::is_base_of<T, T2>::value, "incompatible _Ref types");
68 _ptr = o._ptr;
69 _isValid = true;
71 template <typename T2>
72 _Ref(T2* o) {
73 typedef typename std::remove_const<T2>::type T2B;
74 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
75 if ((FLAGS & REF_Nullable) == 0)
76 assert(o != nullptr);
77 _ptr = o;
78 _isValid = true;
80 _Ref(std::nullptr_t) {
81 guarantee<(FLAGS & REF_Nullable) != 0>("nullptr not allowed here");
82 _ptr = nullptr;
83 _isValid = true;
86 template <typename T2, unsigned FLAGS2>
87 _Ref& operator =(_Ref<T2, FLAGS2> o) {
88 static_assert((~FLAGS & FLAGS2) == 0, "incompatible _Ref flags");
89 //static_assert(std::is_base_of<T, T2>::value, "incompatible _Ref types");
90 _ptr = o._ptr;
91 _isValid = o._isValid;
93 template <typename T2>
94 _Ref& operator =(T2* o) {
95 typedef typename std::remove_const<T2>::type T2B;
96 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
97 if ((FLAGS & REF_Nullable) == 0)
98 assert(o != nullptr);
99 _ptr = o;
100 _isValid = true;
102 _Ref& operator =(std::nullptr_t) {
103 guarantee<(FLAGS & REF_Nullable) != 0>("nullptr not allowed here");
104 _ptr = nullptr;
105 _isValid = true;
109 bool isNull() const {
110 if ((FLAGS & REF_Nullable) == 0)
111 return false;
112 return _ptr == nullptr;
114 _Ref<T,FLAGS & ~REF_Nullable> removeNullType() const {
115 if ((FLAGS & REF_Nullable) == 0)
116 return _ptr;
117 assert(_ptr != nullptr);
118 return _ptr;
121 PtrType _ptr;
122 bool _isValid;
125 // Ref represents a nonnull pointer to some object.
127 template <typename T>
128 using Ref = _Ref<typename std::remove_const<T>::type,
129 (std::is_const<T>::value ? REF_Const : REF_Any)>;
131 // RefOrNull represents a normal pointer to some object. Accessing the
132 // data is achieved thru removeNullType, after which the "->" operator
133 // is accessible. Calling removeNullType without checking isNull first
134 // is considered a bug.
135 // The concept is taken from the Ceylon language which handles null
136 // pointers very nicely thru a clever type system.
138 template <typename T>
139 using RefOrNull = _Ref<typename std::remove_const<T>::type,
140 (std::is_const<T>::value ? REF_Const : REF_Any)
141 + REF_Nullable>;
142 } // end of namespace jitcs
144 #endif
145 // _JITCS_ADT_REF_H_