1 //===-- jitcs_adt_ref.h - pointer helper type -------------------*- C++ -*-===//
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.)
10 //===----------------------------------------------------------------------===//
12 #ifndef _JITCS_ADT_REF_H_
13 #define _JITCS_ADT_REF_H_
16 #include <type_traits>
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
>
34 typedef typename
std::add_const
<T
>::type CType
;
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
;
42 guarantee
<(FLAGS
& REF_Nullable
) != 0>
43 ("Default constructor only for nullable refs");
47 _Ref(const _Ref
&) = default;
48 _Ref
& operator = (const _Ref
&) = default;
53 PtrType
operator ->() {
54 guarantee
<(FLAGS
& REF_Nullable
) == 0>
55 ("dereferencing only for non-nullable refs, remove nullable first");
58 RefType
operator *() {
59 guarantee
<(FLAGS
& REF_Nullable
) == 0>
60 ("dereferencing only for non-nullable refs, remove nullable first");
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");
70 template <typename T2
>
72 typedef typename
std::remove_const
<T2
>::type T2B
;
73 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
74 if ((FLAGS
& REF_Nullable
) == 0)
79 _Ref(std::nullptr_t
) {
80 guarantee
<(FLAGS
& REF_Nullable
) != 0>("nullptr not allowed here");
85 template <typename T2
, unsigned FLAGS2
>
86 _Ref
& operator =(_Ref
<T2
, FLAGS2
> o
) {
87 static_assert((~FLAGS
& FLAGS2
) == 0, "incompatible _Ref flags");
88 //static_assert(std::is_base_of<T, T2>::value, "incompatible _Ref types");
90 _isValid
= o
._isValid
;
92 template <typename T2
>
93 _Ref
& operator =(T2
* o
) {
94 typedef typename
std::remove_const
<T2
>::type T2B
;
95 //static_assert(std::is_base_of<T, T2B>::value, "incompatible _Ref types");
96 if ((FLAGS
& REF_Nullable
) == 0)
101 _Ref
& operator =(std::nullptr_t
) {
102 guarantee
<(FLAGS
& REF_Nullable
) != 0>("nullptr not allowed here");
108 bool isNull() const {
109 if ((FLAGS
& REF_Nullable
) == 0)
111 return _ptr
== nullptr;
113 _Ref
<T
,FLAGS
& ~REF_Nullable
> removeNullType() const {
114 if ((FLAGS
& REF_Nullable
) == 0)
116 assert(_ptr
!= nullptr);
124 // Ref represents a nonnull pointer to some object.
126 template <typename T
>
127 using Ref
= _Ref
<typename
std::remove_const
<T
>::type
,
128 (std::is_const
<T
>::value
? REF_Const
: REF_Any
)>;
130 // RefOrNull represents a normal pointer to some object. Accessing the
131 // data is achieved thru removeNullType, after which the "->" operator
132 // is accessible. Calling removeNullType without checking isNull first
133 // is considered a bug.
134 // The concept is taken from the Ceylon language which handles null
135 // pointers very nicely thru a clever type system.
137 template <typename T
>
138 using RefOrNull
= _Ref
<typename
std::remove_const
<T
>::type
,
139 (std::is_const
<T
>::value
? REF_Const
: REF_Any
)
141 } // end of namespace jitcs