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");
71 template <typename T2
>
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)
80 _Ref(std::nullptr_t
) {
81 guarantee
<(FLAGS
& REF_Nullable
) != 0>("nullptr not allowed here");
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");
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)
102 _Ref
& operator =(std::nullptr_t
) {
103 guarantee
<(FLAGS
& REF_Nullable
) != 0>("nullptr not allowed here");
109 bool isNull() const {
110 if ((FLAGS
& REF_Nullable
) == 0)
112 return _ptr
== nullptr;
114 _Ref
<T
,FLAGS
& ~REF_Nullable
> removeNullType() const {
115 if ((FLAGS
& REF_Nullable
) == 0)
117 assert(_ptr
!= nullptr);
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
)
142 } // end of namespace jitcs