1259698Sdim//===- llvm/ADT/polymorphic_ptr.h - Smart copyable owned ptr ----*- C++ -*-===// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim/// \file 10259698Sdim/// This file provides a polymorphic_ptr class template. See the class comments 11259698Sdim/// for details about this API, its intended use cases, etc. 12259698Sdim/// 13259698Sdim/// The primary motivation here is to work around the necessity of copy 14259698Sdim/// semantics in C++98. This is typically used where any actual copies are 15259698Sdim/// incidental or unnecessary. As a consequence, it is expected to cease to be 16259698Sdim/// useful and be removed when we can directly rely on move-only types. 17259698Sdim/// 18259698Sdim//===----------------------------------------------------------------------===// 19259698Sdim 20259698Sdim#ifndef LLVM_ADT_POLYMORPHIC_PTR_H 21259698Sdim#define LLVM_ADT_POLYMORPHIC_PTR_H 22259698Sdim 23259698Sdim#include "llvm/Support/Compiler.h" 24259698Sdim 25259698Sdimnamespace llvm { 26259698Sdim 27259698Sdim/// \brief An owning, copyable polymorphic smart pointer. 28259698Sdim/// 29259698Sdim/// This pointer exists to provide copyable owned smart pointer. Rather than 30259698Sdim/// shared ownership semantics, it has unique ownership semantics and deep copy 31259698Sdim/// semantics. It is copyable by requiring that the underlying type exposes 32259698Sdim/// a method which can produce a (heap allocated) clone. 33259698Sdim/// 34259698Sdim/// Note that in almost all scenarios use of this could be avoided if we could 35259698Sdim/// build move-only containers of a std::unique_ptr, but until then this 36259698Sdim/// provides an effective way to place polymorphic objects in a container. 37259698Sdimtemplate <typename T> class polymorphic_ptr { 38259698Sdim T *ptr; 39259698Sdim 40259698Sdimpublic: 41259698Sdim polymorphic_ptr(T *ptr = 0) : ptr(ptr) {} 42259698Sdim polymorphic_ptr(const polymorphic_ptr &arg) : ptr(arg ? arg->clone() : 0) {} 43259698Sdim#if LLVM_HAS_RVALUE_REFERENCES 44259698Sdim polymorphic_ptr(polymorphic_ptr &&arg) : ptr(arg.take()) {} 45259698Sdim#endif 46259698Sdim ~polymorphic_ptr() { delete ptr; } 47259698Sdim 48259698Sdim polymorphic_ptr &operator=(polymorphic_ptr arg) { 49259698Sdim swap(arg); 50259698Sdim return *this; 51259698Sdim } 52259698Sdim polymorphic_ptr &operator=(T *arg) { 53259698Sdim if (arg != ptr) { 54259698Sdim delete ptr; 55259698Sdim ptr = arg; 56259698Sdim } 57259698Sdim return *this; 58259698Sdim } 59259698Sdim 60259698Sdim T &operator*() const { return *ptr; } 61259698Sdim T *operator->() const { return ptr; } 62259698Sdim LLVM_EXPLICIT operator bool() const { return ptr != 0; } 63259698Sdim bool operator!() const { return ptr == 0; } 64259698Sdim 65259698Sdim T *get() const { return ptr; } 66259698Sdim 67259698Sdim T *take() { 68259698Sdim T *tmp = ptr; 69259698Sdim ptr = 0; 70259698Sdim return tmp; 71259698Sdim } 72259698Sdim 73259698Sdim void swap(polymorphic_ptr &arg) { 74259698Sdim T *tmp = ptr; 75259698Sdim ptr = arg.ptr; 76259698Sdim arg.ptr = tmp; 77259698Sdim } 78259698Sdim}; 79259698Sdim 80259698Sdimtemplate <typename T> 81259698Sdimvoid swap(polymorphic_ptr<T> &lhs, polymorphic_ptr<T> &rhs) { 82259698Sdim lhs.swap(rhs); 83259698Sdim} 84259698Sdim 85259698Sdimtemplate <typename T, typename U> 86259698Sdimbool operator==(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { 87259698Sdim return lhs.get() == rhs.get(); 88259698Sdim} 89259698Sdim 90259698Sdimtemplate <typename T, typename U> 91259698Sdimbool operator!=(const polymorphic_ptr<T> &lhs, const polymorphic_ptr<U> &rhs) { 92259698Sdim return lhs.get() != rhs.get(); 93259698Sdim} 94259698Sdim 95259698Sdimtemplate <typename T, typename U> 96259698Sdimbool operator==(const polymorphic_ptr<T> &lhs, U *rhs) { 97259698Sdim return lhs.get() == rhs; 98259698Sdim} 99259698Sdim 100259698Sdimtemplate <typename T, typename U> 101259698Sdimbool operator!=(const polymorphic_ptr<T> &lhs, U *rhs) { 102259698Sdim return lhs.get() != rhs; 103259698Sdim} 104259698Sdim 105259698Sdimtemplate <typename T, typename U> 106259698Sdimbool operator==(T *lhs, const polymorphic_ptr<U> &rhs) { 107259698Sdim return lhs == rhs.get(); 108259698Sdim} 109259698Sdim 110259698Sdimtemplate <typename T, typename U> 111259698Sdimbool operator!=(T *lhs, const polymorphic_ptr<U> &rhs) { 112259698Sdim return lhs != rhs.get(); 113259698Sdim} 114259698Sdim 115259698Sdim} 116259698Sdim 117259698Sdim#endif 118