1//===----------------------------------------------------------------------===//
2// DuckDB
3//
4// duckdb/common/optional_ptr.hpp
5//
6//
7//===----------------------------------------------------------------------===//
8
9#pragma once
10
11#include "duckdb/common/exception.hpp"
12#include "duckdb/common/unique_ptr.hpp"
13
14namespace duckdb {
15
16template <class T>
17class optional_ptr {
18public:
19 optional_ptr() : ptr(nullptr) {
20 }
21 optional_ptr(T *ptr_p) : ptr(ptr_p) { // NOLINT: allow implicit creation from pointer
22 }
23 optional_ptr(const unique_ptr<T> &ptr_p) : ptr(ptr_p.get()) { // NOLINT: allow implicit creation from unique pointer
24 }
25
26 void CheckValid() const {
27 if (!ptr) {
28 throw InternalException("Attempting to dereference an optional pointer that is not set");
29 }
30 }
31
32 operator bool() const {
33 return ptr;
34 }
35 T &operator*() {
36 CheckValid();
37 return *ptr;
38 }
39 const T &operator*() const {
40 CheckValid();
41 return *ptr;
42 }
43 T *operator->() {
44 CheckValid();
45 return ptr;
46 }
47 const T *operator->() const {
48 CheckValid();
49 return ptr;
50 }
51 T *get() {
52 // CheckValid();
53 return ptr;
54 }
55 const T *get() const {
56 // CheckValid();
57 return ptr;
58 }
59 // this looks dirty - but this is the default behavior of raw pointers
60 T *get_mutable() const {
61 // CheckValid();
62 return ptr;
63 }
64
65 bool operator==(const optional_ptr<T> &rhs) const {
66 return ptr == rhs.ptr;
67 }
68
69 bool operator!=(const optional_ptr<T> &rhs) const {
70 return ptr != rhs.ptr;
71 }
72
73private:
74 T *ptr;
75};
76
77} // namespace duckdb
78