1*38e8c45fSAndroid Build Coastguard Worker /* 2*38e8c45fSAndroid Build Coastguard Worker * Copyright 2022 The Android Open Source Project 3*38e8c45fSAndroid Build Coastguard Worker * 4*38e8c45fSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*38e8c45fSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*38e8c45fSAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*38e8c45fSAndroid Build Coastguard Worker * 8*38e8c45fSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*38e8c45fSAndroid Build Coastguard Worker * 10*38e8c45fSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*38e8c45fSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*38e8c45fSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*38e8c45fSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*38e8c45fSAndroid Build Coastguard Worker * limitations under the License. 15*38e8c45fSAndroid Build Coastguard Worker */ 16*38e8c45fSAndroid Build Coastguard Worker 17*38e8c45fSAndroid Build Coastguard Worker #pragma once 18*38e8c45fSAndroid Build Coastguard Worker 19*38e8c45fSAndroid Build Coastguard Worker #include <cstdlib> 20*38e8c45fSAndroid Build Coastguard Worker #include <type_traits> 21*38e8c45fSAndroid Build Coastguard Worker #include <utility> 22*38e8c45fSAndroid Build Coastguard Worker 23*38e8c45fSAndroid Build Coastguard Worker namespace android::ftl { 24*38e8c45fSAndroid Build Coastguard Worker 25*38e8c45fSAndroid Build Coastguard Worker // Enforces and documents non-null pre/post-condition for (raw or smart) pointers. 26*38e8c45fSAndroid Build Coastguard Worker // 27*38e8c45fSAndroid Build Coastguard Worker // void get_length(const ftl::NonNull<std::shared_ptr<std::string>>& string_ptr, 28*38e8c45fSAndroid Build Coastguard Worker // ftl::NonNull<std::size_t*> length_ptr) { 29*38e8c45fSAndroid Build Coastguard Worker // // No need for `nullptr` checks. 30*38e8c45fSAndroid Build Coastguard Worker // *length_ptr = string_ptr->length(); 31*38e8c45fSAndroid Build Coastguard Worker // } 32*38e8c45fSAndroid Build Coastguard Worker // 33*38e8c45fSAndroid Build Coastguard Worker // const auto string_ptr = ftl::as_non_null(std::make_shared<std::string>("android")); 34*38e8c45fSAndroid Build Coastguard Worker // std::size_t size; 35*38e8c45fSAndroid Build Coastguard Worker // get_length(string_ptr, ftl::as_non_null(&size)); 36*38e8c45fSAndroid Build Coastguard Worker // assert(size == 7u); 37*38e8c45fSAndroid Build Coastguard Worker // 38*38e8c45fSAndroid Build Coastguard Worker // For compatibility with std::unique_ptr<T> and performance with std::shared_ptr<T>, move 39*38e8c45fSAndroid Build Coastguard Worker // operations are allowed despite breaking the invariant: 40*38e8c45fSAndroid Build Coastguard Worker // 41*38e8c45fSAndroid Build Coastguard Worker // using Pair = std::pair<ftl::NonNull<std::shared_ptr<int>>, std::shared_ptr<int>>; 42*38e8c45fSAndroid Build Coastguard Worker // 43*38e8c45fSAndroid Build Coastguard Worker // Pair dupe_if(ftl::NonNull<std::unique_ptr<int>> non_null_ptr, bool condition) { 44*38e8c45fSAndroid Build Coastguard Worker // // Move the underlying pointer out, so `non_null_ptr` must not be accessed after this point. 45*38e8c45fSAndroid Build Coastguard Worker // auto unique_ptr = std::move(non_null_ptr).take(); 46*38e8c45fSAndroid Build Coastguard Worker // 47*38e8c45fSAndroid Build Coastguard Worker // auto non_null_shared_ptr = ftl::as_non_null(std::shared_ptr<int>(std::move(unique_ptr))); 48*38e8c45fSAndroid Build Coastguard Worker // auto nullable_shared_ptr = condition ? non_null_shared_ptr.get() : nullptr; 49*38e8c45fSAndroid Build Coastguard Worker // 50*38e8c45fSAndroid Build Coastguard Worker // return {std::move(non_null_shared_ptr), std::move(nullable_shared_ptr)}; 51*38e8c45fSAndroid Build Coastguard Worker // } 52*38e8c45fSAndroid Build Coastguard Worker // 53*38e8c45fSAndroid Build Coastguard Worker // auto ptr = ftl::as_non_null(std::make_unique<int>(42)); 54*38e8c45fSAndroid Build Coastguard Worker // const auto [ptr1, ptr2] = dupe_if(std::move(ptr), true); 55*38e8c45fSAndroid Build Coastguard Worker // assert(ptr1.get() == ptr2); 56*38e8c45fSAndroid Build Coastguard Worker // 57*38e8c45fSAndroid Build Coastguard Worker template <typename Pointer> 58*38e8c45fSAndroid Build Coastguard Worker class NonNull final { 59*38e8c45fSAndroid Build Coastguard Worker struct Passkey {}; 60*38e8c45fSAndroid Build Coastguard Worker 61*38e8c45fSAndroid Build Coastguard Worker public: 62*38e8c45fSAndroid Build Coastguard Worker // Disallow `nullptr` explicitly for clear compilation errors. 63*38e8c45fSAndroid Build Coastguard Worker NonNull() = delete; 64*38e8c45fSAndroid Build Coastguard Worker NonNull(std::nullptr_t) = delete; 65*38e8c45fSAndroid Build Coastguard Worker 66*38e8c45fSAndroid Build Coastguard Worker // Copy operations. 67*38e8c45fSAndroid Build Coastguard Worker 68*38e8c45fSAndroid Build Coastguard Worker constexpr NonNull(const NonNull&) = default; 69*38e8c45fSAndroid Build Coastguard Worker constexpr NonNull& operator=(const NonNull&) = default; 70*38e8c45fSAndroid Build Coastguard Worker 71*38e8c45fSAndroid Build Coastguard Worker template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, Pointer>>> NonNull(const NonNull<U> & other)72*38e8c45fSAndroid Build Coastguard Worker constexpr NonNull(const NonNull<U>& other) : pointer_(other.get()) {} 73*38e8c45fSAndroid Build Coastguard Worker 74*38e8c45fSAndroid Build Coastguard Worker template <typename U, typename = std::enable_if_t<std::is_convertible_v<U, Pointer>>> 75*38e8c45fSAndroid Build Coastguard Worker constexpr NonNull& operator=(const NonNull<U>& other) { 76*38e8c45fSAndroid Build Coastguard Worker pointer_ = other.get(); 77*38e8c45fSAndroid Build Coastguard Worker return *this; 78*38e8c45fSAndroid Build Coastguard Worker } 79*38e8c45fSAndroid Build Coastguard Worker get()80*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr const Pointer& get() const { return pointer_; } 81*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr explicit operator const Pointer&() const { return get(); } 82*38e8c45fSAndroid Build Coastguard Worker 83*38e8c45fSAndroid Build Coastguard Worker // Move operations. These break the invariant, so care must be taken to avoid subsequent access. 84*38e8c45fSAndroid Build Coastguard Worker 85*38e8c45fSAndroid Build Coastguard Worker constexpr NonNull(NonNull&&) = default; 86*38e8c45fSAndroid Build Coastguard Worker constexpr NonNull& operator=(NonNull&&) = default; 87*38e8c45fSAndroid Build Coastguard Worker take()88*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr Pointer take() && { return std::move(pointer_); } Pointer()89*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr explicit operator Pointer() && { return take(); } 90*38e8c45fSAndroid Build Coastguard Worker 91*38e8c45fSAndroid Build Coastguard Worker // Dereferencing. decltype(auto)92*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr decltype(auto) operator*() const { return *get(); } 93*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr decltype(auto) operator->() const { return get(); } 94*38e8c45fSAndroid Build Coastguard Worker 95*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr explicit operator bool() const { return !(pointer_ == nullptr); } 96*38e8c45fSAndroid Build Coastguard Worker 97*38e8c45fSAndroid Build Coastguard Worker // Private constructor for ftl::as_non_null. Excluded from candidate constructors for conversions 98*38e8c45fSAndroid Build Coastguard Worker // through the passkey idiom, for clear compilation errors. 99*38e8c45fSAndroid Build Coastguard Worker template <typename P> NonNull(Passkey,P && pointer)100*38e8c45fSAndroid Build Coastguard Worker constexpr NonNull(Passkey, P&& pointer) : pointer_(std::forward<P>(pointer)) { 101*38e8c45fSAndroid Build Coastguard Worker if (pointer_ == nullptr) std::abort(); 102*38e8c45fSAndroid Build Coastguard Worker } 103*38e8c45fSAndroid Build Coastguard Worker 104*38e8c45fSAndroid Build Coastguard Worker private: 105*38e8c45fSAndroid Build Coastguard Worker template <typename P> 106*38e8c45fSAndroid Build Coastguard Worker friend constexpr auto as_non_null(P&&) -> NonNull<std::decay_t<P>>; 107*38e8c45fSAndroid Build Coastguard Worker 108*38e8c45fSAndroid Build Coastguard Worker Pointer pointer_; 109*38e8c45fSAndroid Build Coastguard Worker }; 110*38e8c45fSAndroid Build Coastguard Worker 111*38e8c45fSAndroid Build Coastguard Worker template <typename P> 112*38e8c45fSAndroid Build Coastguard Worker [[nodiscard]] constexpr auto as_non_null(P&& pointer) -> NonNull<std::decay_t<P>> { 113*38e8c45fSAndroid Build Coastguard Worker using Passkey = typename NonNull<std::decay_t<P>>::Passkey; 114*38e8c45fSAndroid Build Coastguard Worker return {Passkey{}, std::forward<P>(pointer)}; 115*38e8c45fSAndroid Build Coastguard Worker } 116*38e8c45fSAndroid Build Coastguard Worker 117*38e8c45fSAndroid Build Coastguard Worker // NonNull<P> <=> NonNull<Q> 118*38e8c45fSAndroid Build Coastguard Worker 119*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 120*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator==(const NonNull<P>& lhs, const NonNull<Q>& rhs) { 121*38e8c45fSAndroid Build Coastguard Worker return lhs.get() == rhs.get(); 122*38e8c45fSAndroid Build Coastguard Worker } 123*38e8c45fSAndroid Build Coastguard Worker 124*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 125*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator!=(const NonNull<P>& lhs, const NonNull<Q>& rhs) { 126*38e8c45fSAndroid Build Coastguard Worker return !operator==(lhs, rhs); 127*38e8c45fSAndroid Build Coastguard Worker } 128*38e8c45fSAndroid Build Coastguard Worker 129*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 130*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator<(const NonNull<P>& lhs, const NonNull<Q>& rhs) { 131*38e8c45fSAndroid Build Coastguard Worker return lhs.get() < rhs.get(); 132*38e8c45fSAndroid Build Coastguard Worker } 133*38e8c45fSAndroid Build Coastguard Worker 134*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 135*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator<=(const NonNull<P>& lhs, const NonNull<Q>& rhs) { 136*38e8c45fSAndroid Build Coastguard Worker return lhs.get() <= rhs.get(); 137*38e8c45fSAndroid Build Coastguard Worker } 138*38e8c45fSAndroid Build Coastguard Worker 139*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 140*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator>=(const NonNull<P>& lhs, const NonNull<Q>& rhs) { 141*38e8c45fSAndroid Build Coastguard Worker return lhs.get() >= rhs.get(); 142*38e8c45fSAndroid Build Coastguard Worker } 143*38e8c45fSAndroid Build Coastguard Worker 144*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 145*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator>(const NonNull<P>& lhs, const NonNull<Q>& rhs) { 146*38e8c45fSAndroid Build Coastguard Worker return lhs.get() > rhs.get(); 147*38e8c45fSAndroid Build Coastguard Worker } 148*38e8c45fSAndroid Build Coastguard Worker 149*38e8c45fSAndroid Build Coastguard Worker // NonNull<P> <=> Q 150*38e8c45fSAndroid Build Coastguard Worker 151*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 152*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator==(const NonNull<P>& lhs, const Q& rhs) { 153*38e8c45fSAndroid Build Coastguard Worker return lhs.get() == rhs; 154*38e8c45fSAndroid Build Coastguard Worker } 155*38e8c45fSAndroid Build Coastguard Worker 156*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 157*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator!=(const NonNull<P>& lhs, const Q& rhs) { 158*38e8c45fSAndroid Build Coastguard Worker return lhs.get() != rhs; 159*38e8c45fSAndroid Build Coastguard Worker } 160*38e8c45fSAndroid Build Coastguard Worker 161*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 162*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator<(const NonNull<P>& lhs, const Q& rhs) { 163*38e8c45fSAndroid Build Coastguard Worker return lhs.get() < rhs; 164*38e8c45fSAndroid Build Coastguard Worker } 165*38e8c45fSAndroid Build Coastguard Worker 166*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 167*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator<=(const NonNull<P>& lhs, const Q& rhs) { 168*38e8c45fSAndroid Build Coastguard Worker return lhs.get() <= rhs; 169*38e8c45fSAndroid Build Coastguard Worker } 170*38e8c45fSAndroid Build Coastguard Worker 171*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 172*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator>=(const NonNull<P>& lhs, const Q& rhs) { 173*38e8c45fSAndroid Build Coastguard Worker return lhs.get() >= rhs; 174*38e8c45fSAndroid Build Coastguard Worker } 175*38e8c45fSAndroid Build Coastguard Worker 176*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 177*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator>(const NonNull<P>& lhs, const Q& rhs) { 178*38e8c45fSAndroid Build Coastguard Worker return lhs.get() > rhs; 179*38e8c45fSAndroid Build Coastguard Worker } 180*38e8c45fSAndroid Build Coastguard Worker 181*38e8c45fSAndroid Build Coastguard Worker // P <=> NonNull<Q> 182*38e8c45fSAndroid Build Coastguard Worker 183*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 184*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator==(const P& lhs, const NonNull<Q>& rhs) { 185*38e8c45fSAndroid Build Coastguard Worker return lhs == rhs.get(); 186*38e8c45fSAndroid Build Coastguard Worker } 187*38e8c45fSAndroid Build Coastguard Worker 188*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 189*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator!=(const P& lhs, const NonNull<Q>& rhs) { 190*38e8c45fSAndroid Build Coastguard Worker return lhs != rhs.get(); 191*38e8c45fSAndroid Build Coastguard Worker } 192*38e8c45fSAndroid Build Coastguard Worker 193*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 194*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator<(const P& lhs, const NonNull<Q>& rhs) { 195*38e8c45fSAndroid Build Coastguard Worker return lhs < rhs.get(); 196*38e8c45fSAndroid Build Coastguard Worker } 197*38e8c45fSAndroid Build Coastguard Worker 198*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 199*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator<=(const P& lhs, const NonNull<Q>& rhs) { 200*38e8c45fSAndroid Build Coastguard Worker return lhs <= rhs.get(); 201*38e8c45fSAndroid Build Coastguard Worker } 202*38e8c45fSAndroid Build Coastguard Worker 203*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 204*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator>=(const P& lhs, const NonNull<Q>& rhs) { 205*38e8c45fSAndroid Build Coastguard Worker return lhs >= rhs.get(); 206*38e8c45fSAndroid Build Coastguard Worker } 207*38e8c45fSAndroid Build Coastguard Worker 208*38e8c45fSAndroid Build Coastguard Worker template <typename P, typename Q> 209*38e8c45fSAndroid Build Coastguard Worker constexpr bool operator>(const P& lhs, const NonNull<Q>& rhs) { 210*38e8c45fSAndroid Build Coastguard Worker return lhs > rhs.get(); 211*38e8c45fSAndroid Build Coastguard Worker } 212*38e8c45fSAndroid Build Coastguard Worker 213*38e8c45fSAndroid Build Coastguard Worker } // namespace android::ftl 214*38e8c45fSAndroid Build Coastguard Worker 215*38e8c45fSAndroid Build Coastguard Worker // Specialize std::hash for ftl::NonNull<T> 216*38e8c45fSAndroid Build Coastguard Worker template <typename P> 217*38e8c45fSAndroid Build Coastguard Worker struct std::hash<android::ftl::NonNull<P>> { 218*38e8c45fSAndroid Build Coastguard Worker std::size_t operator()(const android::ftl::NonNull<P>& ptr) const { 219*38e8c45fSAndroid Build Coastguard Worker return std::hash<P>()(ptr.get()); 220*38e8c45fSAndroid Build Coastguard Worker } 221*38e8c45fSAndroid Build Coastguard Worker }; 222