Adding copyright notices to most files. Also add readme file, and some
[jitcs.git] / include / jitcs_adt_ref.h
blob0de49a876f2121a2f425276b9da26c098b2515be
1 //===-- jitcs_adt_ref.h -----------------------------------------*- C++ -*-===//
2 // An attributed pointer class.
3 //
4 // Copyright (C) 2013-2014 Dirk Steinke.
5 // See copyright and license notice in COPYRIGHT or include/jitcs.h
6 //
7 // A Ref or RefOrNull pointer object NEVER owns the object pointed to.
8 // A Ref pointer can never contain a null pointer. A RefOrNull object cannot
9 // directly use the -> operator. You can check for isNull(), and
10 // removeNullType() if it is not.
11 // (The principle of this is taken from the language Ceylon which, according
12 // to my understanding, handles null pointers quite nicely.)
13 //===----------------------------------------------------------------------===//
15 #ifndef _JITCS_ADT_REF_H_
16 #define _JITCS_ADT_REF_H_
18 #include <assert.h>
19 #include <type_traits>
21 namespace jitcs {
22 enum {
23 REF_Any = 0,
24 REF_Nullable = 1,
25 REF_Const = 2,
28 template <bool b, typename = typename std::enable_if<b,int>::type>
29 void guarantee(const char *) {}
31 // _Ref is an attributed pointer type.
32 // Currently it supports the const-attribute of its data, and
33 // the nonnull-attribute of the pointer.
35 template <typename T, unsigned FLAGS>
36 struct _Ref {
37 typedef typename std::add_const<T>::type CType;
38 typedef T NCType;
39 static const bool IsConstRef = (FLAGS & REF_Const) != 0;
40 typedef typename std::conditional<IsConstRef, CType, NCType>::type Type;
41 typedef Type* PtrType;
42 typedef Type& RefType;
44 _Ref() {
45 guarantee<(FLAGS & REF_Nullable) != 0>
46 ("Default constructor only for nullable refs");
47 _ptr = nullptr;
48 _isValid = false;
50 _Ref(const _Ref&) = default;
51 _Ref& operator = (const _Ref&) = default;
52 PtrType ptr() {
53 assert(_isValid);
54 return _ptr;
56 PtrType operator ->() {
57 guarantee<(FLAGS & REF_Nullable) == 0>
58 ("dereferencing only for non-nullable refs, remove nullable first");
59 return ptr();
61 RefType operator *() {
62 guarantee<(FLAGS & REF_Nullable) == 0>
63 ("dereferencing only for non-nullable refs, remove nullable first");
64 return *ptr();
67 template <typename T2, unsigned FLAGS2>
68 _Ref(_Ref<T2, FLAGS2> o) {
69 static_assert((~FLAGS & FLAGS2) == 0, "incompatible _Ref flags");
70 //static_assert(std::is_base_of<T, T2>::value, "incompatible _Ref types");
71 _ptr = o._ptr;
72 _isValid = true;
74 template <typename T2>
75 _Ref(T2* o) {
76 typedef typename std::remove_const<T2>::type T2B;
77 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
78 if ((FLAGS & REF_Nullable) == 0)
79 assert(o != nullptr);
80 _ptr = o;
81 _isValid = true;
83 _Ref(std::nullptr_t) {
84 guarantee<(FLAGS & REF_Nullable) != 0>("nullptr not allowed here");
85 _ptr = nullptr;
86 _isValid = true;
89 template <typename T2, unsigned FLAGS2>
90 _Ref& operator =(_Ref<T2, FLAGS2> o) {
91 static_assert((~FLAGS & FLAGS2) == 0, "incompatible _Ref flags");
92 //static_assert(std::is_base_of<T, T2>::value, "incompatible _Ref types");
93 _ptr = o._ptr;
94 _isValid = o._isValid;
96 template <typename T2>
97 _Ref& operator =(T2* o) {
98 typedef typename std::remove_const<T2>::type T2B;
99 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
100 if ((FLAGS & REF_Nullable) == 0)
101 assert(o != nullptr);
102 _ptr = o;
103 _isValid = true;
105 _Ref& operator =(std::nullptr_t) {
106 guarantee<(FLAGS & REF_Nullable) != 0>("nullptr not allowed here");
107 _ptr = nullptr;
108 _isValid = true;
112 bool isNull() const {
113 if ((FLAGS & REF_Nullable) == 0)
114 return false;
115 return _ptr == nullptr;
117 _Ref<T,FLAGS & ~REF_Nullable> removeNullType() const {
118 if ((FLAGS & REF_Nullable) == 0)
119 return _ptr;
120 assert(_ptr != nullptr);
121 return _ptr;
124 PtrType _ptr;
125 bool _isValid;
128 // Ref represents a nonnull pointer to some object.
130 template <typename T>
131 using Ref = _Ref<typename std::remove_const<T>::type,
132 (std::is_const<T>::value ? REF_Const : REF_Any)>;
134 // RefOrNull represents a normal pointer to some object. Accessing the
135 // data is achieved thru removeNullType, after which the "->" operator
136 // is accessible. Calling removeNullType without checking isNull first
137 // is considered a bug.
138 // The concept is taken from the Ceylon language which handles null
139 // pointers very nicely thru a clever type system.
141 template <typename T>
142 using RefOrNull = _Ref<typename std::remove_const<T>::type,
143 (std::is_const<T>::value ? REF_Const : REF_Any)
144 + REF_Nullable>;
145 } // end of namespace jitcs
147 #endif
148 // _JITCS_ADT_REF_H_