1 //===-- include/flang/Common/reference.h ------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 // Implements a better std::reference_wrapper<> template class with 10 // move semantics, equality testing, and member access. 11 // Use Reference<A> in place of a real A& reference when assignability is 12 // required; safer than a bare pointer because it's guaranteed to not be null. 13 14 #ifndef FORTRAN_COMMON_REFERENCE_H_ 15 #define FORTRAN_COMMON_REFERENCE_H_ 16 #include <type_traits> 17 namespace Fortran::common { 18 template <typename A> class Reference { 19 public: 20 using type = A; Reference(type & x)21 Reference(type &x) : p_{&x} {} Reference(const Reference & that)22 Reference(const Reference &that) : p_{that.p_} {} Reference(Reference && that)23 Reference(Reference &&that) : p_{that.p_} {} 24 Reference &operator=(const Reference &that) { 25 p_ = that.p_; 26 return *this; 27 } 28 Reference &operator=(Reference &&that) { 29 p_ = that.p_; 30 return *this; 31 } 32 33 // Implicit conversions to references are supported only for 34 // const-qualified types in order to avoid any pernicious 35 // creation of a temporary copy in cases like: 36 // Reference<type> ref; 37 // const Type &x{ref}; // creates ref to temp copy! 38 operator std::conditional_t<std::is_const_v<type>, type &, void>() 39 const noexcept { 40 if constexpr (std::is_const_v<type>) { 41 return *p_; 42 } 43 } 44 get()45 type &get() const noexcept { return *p_; } 46 type *operator->() const { return p_; } 47 type &operator*() const { return *p_; } 48 49 bool operator==(std::add_const_t<A> &that) const { 50 return p_ == &that || *p_ == that; 51 } 52 bool operator!=(std::add_const_t<A> &that) const { return !(*this == that); } 53 bool operator==(const Reference &that) const { 54 return p_ == that.p_ || *this == *that.p_; 55 } 56 bool operator!=(const Reference &that) const { return !(*this == that); } 57 58 private: 59 type *p_; // never null 60 }; 61 template <typename A> Reference(A &) -> Reference<A>; 62 } // namespace Fortran::common 63 #endif 64