1 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 2 // -*- Mode: C++ -*- 3 // 4 // Copyright (C) 2019-2022 Google, Inc. 5 6 /// @file 7 8 #ifndef __ABG_CXX_COMPAT_H 9 #define __ABG_CXX_COMPAT_H 10 11 // C++17 support (via custom implementations if compiled with earlier standard) 12 13 #if __cplusplus >= 201703L 14 15 #include <optional> 16 17 #else 18 19 #include <stdexcept> // for throwing std::runtime_error("bad_optional_access") 20 21 #endif 22 23 namespace abg_compat { 24 25 #if __cplusplus >= 201703L 26 27 using std::optional; 28 29 #else 30 31 // <optional> 32 33 /// Simplified implementation of std::optional just enough to be used as a 34 /// replacement for our purposes and when compiling with pre C++17. 35 /// 36 /// The implementation intentionally does not support a whole lot of features 37 /// to minimize the maintenance effort with this. 38 template <typename T> class optional 39 { 40 bool has_value_; 41 T value_; 42 43 public: 44 optional() : has_value_(false), value_() {} 45 optional(const T& value) : has_value_(true), value_(value) {} 46 47 bool 48 has_value() const noexcept 49 { 50 return has_value_; 51 } 52 53 const T& 54 value() const 55 { 56 if (!has_value_) 57 throw std::runtime_error("bad_optional_access"); 58 return value_; 59 } 60 61 const T 62 value_or(const T& default_value) const 63 { 64 if (!has_value_) 65 return default_value; 66 return value_; 67 } 68 69 const T& 70 operator*() const& noexcept 71 { return value_; } 72 73 T& 74 operator*() & noexcept 75 { return value_; } 76 77 const T* 78 operator->() const noexcept 79 { return &value_; } 80 81 T* 82 operator->() noexcept 83 { return &value_; } 84 85 optional& 86 operator=(const T& value) 87 { 88 has_value_ = true; 89 value_ = value; 90 return *this; 91 } 92 93 explicit operator bool() const noexcept { return has_value(); } 94 }; 95 96 template <typename T, typename U> 97 bool 98 operator==(const optional<T>& lhs, const optional<U>& rhs) 99 { 100 if (!lhs.has_value() && !rhs.has_value()) 101 return true; 102 if (!lhs.has_value() || !rhs.has_value()) 103 return false; 104 return lhs.value() == rhs.value(); 105 } 106 107 template <typename T, typename U> 108 bool 109 operator!=(const optional<T>& lhs, const optional<U>& rhs) 110 { 111 return !(lhs == rhs); 112 } 113 114 #endif 115 } 116 117 #endif // __ABG_CXX_COMPAT_H 118