1//===- llvm/ADT/polymorphic_ptr.h - Smart copyable owned ptr ----*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9/// \file 10/// This file provides a polymorphic_ptr class template. See the class comments 11/// for details about this API, its intended use cases, etc. 12/// 13/// The primary motivation here is to work around the necessity of copy 14/// semantics in C++98. This is typically used where any actual copies are 15/// incidental or unnecessary. As a consequence, it is expected to cease to be 16/// useful and be removed when we can directly rely on move-only types. 17/// 18//===----------------------------------------------------------------------===// 19 20#ifndef LLVM_ADT_POLYMORPHIC_PTR_H 21#define LLVM_ADT_POLYMORPHIC_PTR_H 22 23#include "llvm/Support/Compiler.h" 24 25namespace llvm { 26 27/// \brief An owning, copyable polymorphic smart pointer. 28/// 29/// This pointer exists to provide copyable owned smart pointer. Rather than 30/// shared ownership semantics, it has unique ownership semantics and deep copy 31/// semantics. It is copyable by requiring that the underlying type exposes 32/// a method which can produce a (heap allocated) clone. 33/// 34/// Note that in almost all scenarios use of this could be avoided if we could 35/// build move-only containers of a std::unique_ptr, but until then this 36/// provides an effective way to place polymorphic objects in a container. 37template <typename T> class polymorphic_ptr { 38 T *ptr; 39 40public: 41 polymorphic_ptr(T *ptr = 0) : ptr(ptr) {} 42 polymorphic_ptr(const polymorphic_ptr &arg) : ptr(arg ? arg->clone() : 0) {} 43#if LLVM_HAS_RVALUE_REFERENCES 44 polymorphic_ptr(polymorphic_ptr &&arg) : ptr(arg.take()) {} 45#endif 46 ~polymorphic_ptr() { delete ptr; } 47 48 polymorphic_ptr &operator=(polymorphic_ptr arg) { 49 swap(arg); 50 return *this; 51 } 52 polymorphic_ptr &operator=(T *arg) { 53 if (arg != ptr) { 54 delete ptr; 55 ptr = arg; 56 } 57 return *this; 58 } 59 60 T &operator*() const { return *ptr; } 61 T *operator->() const { return ptr; } 62 LLVM_EXPLICIT operator bool() const { return ptr != 0; } 63 bool operator!() const { return ptr == 0; } 64 65 T *get() const { return ptr; } 66 67 T *take() { 68 T *tmp = ptr; 69 ptr = 0; 70 return tmp; 71 } 72 73 void swap(polymorphic_ptr &arg) { 74 T *tmp = ptr; 75 ptr = arg.ptr; 76 arg.ptr = tmp; 77 } 78}; 79 80template <typename T> 81void swap(polymorphic_ptr<T> &lhs, polymorphic_ptr<T> &rhs) { 82 lhs.swap(rhs); 83} 84 85template <typename T, typename U> 86bool operator==(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { 87 return lhs.get() == rhs.get(); 88} 89 90template <typename T, typename U> 91bool operator!=(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { 92 return lhs.get() != rhs.get(); 93} 94 95template <typename T, typename U> 96bool operator==(const polymorphic_ptr<T> &lhs, U *rhs) { 97 return lhs.get() == rhs; 98} 99 100template <typename T, typename U> 101bool operator!=(const polymorphic_ptr<T> &lhs, U *rhs) { 102 return lhs.get() != rhs; 103} 104 105template <typename T, typename U> 106bool operator==(T *lhs, const polymorphic_ptr<U> &rhs) { 107 return lhs == rhs.get(); 108} 109 110template <typename T, typename U> 111bool operator!=(T *lhs, const polymorphic_ptr<U> &rhs) { 112 return lhs != rhs.get(); 113} 114 115} 116 117#endif 118