164ab3302SCarolineConcatto //===-- include/flang/Common/reference.h ------------------------*- C++ -*-===// 264ab3302SCarolineConcatto // 364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information. 564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 664ab3302SCarolineConcatto // 764ab3302SCarolineConcatto //===----------------------------------------------------------------------===// 864ab3302SCarolineConcatto 964ab3302SCarolineConcatto // Implements a better std::reference_wrapper<> template class with 1064ab3302SCarolineConcatto // move semantics, equality testing, and member access. 1164ab3302SCarolineConcatto // Use Reference<A> in place of a real A& reference when assignability is 1264ab3302SCarolineConcatto // required; safer than a bare pointer because it's guaranteed to not be null. 1364ab3302SCarolineConcatto 1464ab3302SCarolineConcatto #ifndef FORTRAN_COMMON_REFERENCE_H_ 1564ab3302SCarolineConcatto #define FORTRAN_COMMON_REFERENCE_H_ 1664ab3302SCarolineConcatto #include <type_traits> 1764ab3302SCarolineConcatto namespace Fortran::common { 1864ab3302SCarolineConcatto template <typename A> class Reference { 1964ab3302SCarolineConcatto public: 2064ab3302SCarolineConcatto using type = A; Reference(type & x)2164ab3302SCarolineConcatto Reference(type &x) : p_{&x} {} Reference(const Reference & that)2264ab3302SCarolineConcatto Reference(const Reference &that) : p_{that.p_} {} Reference(Reference && that)2364ab3302SCarolineConcatto Reference(Reference &&that) : p_{that.p_} {} 2464ab3302SCarolineConcatto Reference &operator=(const Reference &that) { 2564ab3302SCarolineConcatto p_ = that.p_; 2664ab3302SCarolineConcatto return *this; 2764ab3302SCarolineConcatto } 2864ab3302SCarolineConcatto Reference &operator=(Reference &&that) { 2964ab3302SCarolineConcatto p_ = that.p_; 3064ab3302SCarolineConcatto return *this; 3164ab3302SCarolineConcatto } 3264ab3302SCarolineConcatto 3364ab3302SCarolineConcatto // Implicit conversions to references are supported only for 3464ab3302SCarolineConcatto // const-qualified types in order to avoid any pernicious 3564ab3302SCarolineConcatto // creation of a temporary copy in cases like: 3664ab3302SCarolineConcatto // Reference<type> ref; 3764ab3302SCarolineConcatto // const Type &x{ref}; // creates ref to temp copy! 38*1f879005STim Keith operator std::conditional_t<std::is_const_v<type>, type &, void>() 39*1f879005STim Keith const noexcept { 4064ab3302SCarolineConcatto if constexpr (std::is_const_v<type>) { 4164ab3302SCarolineConcatto return *p_; 4264ab3302SCarolineConcatto } 4364ab3302SCarolineConcatto } 4464ab3302SCarolineConcatto get()4564ab3302SCarolineConcatto type &get() const noexcept { return *p_; } 4664ab3302SCarolineConcatto type *operator->() const { return p_; } 4764ab3302SCarolineConcatto type &operator*() const { return *p_; } 48e03b20e6Speter klausler 49e03b20e6Speter klausler bool operator==(std::add_const_t<A> &that) const { 50e03b20e6Speter klausler return p_ == &that || *p_ == that; 51e03b20e6Speter klausler } 52e03b20e6Speter klausler bool operator!=(std::add_const_t<A> &that) const { return !(*this == that); } 53e03b20e6Speter klausler bool operator==(const Reference &that) const { 54e03b20e6Speter klausler return p_ == that.p_ || *this == *that.p_; 55e03b20e6Speter klausler } 56e03b20e6Speter klausler bool operator!=(const Reference &that) const { return !(*this == that); } 5764ab3302SCarolineConcatto 5864ab3302SCarolineConcatto private: 5964ab3302SCarolineConcatto type *p_; // never null 6064ab3302SCarolineConcatto }; 6164ab3302SCarolineConcatto template <typename A> Reference(A &) -> Reference<A>; 62*1f879005STim Keith } // namespace Fortran::common 6364ab3302SCarolineConcatto #endif 64