LLVM  8.0.1
Any.h
Go to the documentation of this file.
1 //===- Any.h - Generic type erased holder of any type -----------*- 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 //
10 // This file provides Any, a non-template class modeled in the spirit of
11 // std::any. The idea is to provide a type-safe replacement for C's void*.
12 // It can hold a value of any copy-constructible copy-assignable type
13 //
14 //===----------------------------------------------------------------------===//
15 
16 #ifndef LLVM_ADT_ANY_H
17 #define LLVM_ADT_ANY_H
18 
19 #include "llvm/ADT/STLExtras.h"
20 
21 #include <cassert>
22 #include <memory>
23 #include <type_traits>
24 
25 namespace llvm {
26 
27 class Any {
28  template <typename T> struct TypeId { static const char Id; };
29 
30  struct StorageBase {
31  virtual ~StorageBase() = default;
32  virtual std::unique_ptr<StorageBase> clone() const = 0;
33  virtual const void *id() const = 0;
34  };
35 
36  template <typename T> struct StorageImpl : public StorageBase {
37  explicit StorageImpl(const T &Value) : Value(Value) {}
38 
39  explicit StorageImpl(T &&Value) : Value(std::move(Value)) {}
40 
41  std::unique_ptr<StorageBase> clone() const override {
42  return llvm::make_unique<StorageImpl<T>>(Value);
43  }
44 
45  const void *id() const override { return &TypeId<T>::Id; }
46 
47  T Value;
48 
49  private:
50  StorageImpl &operator=(const StorageImpl &Other) = delete;
51  StorageImpl(const StorageImpl &Other) = delete;
52  };
53 
54 public:
55  Any() = default;
56 
57  Any(const Any &Other)
58  : Storage(Other.Storage ? Other.Storage->clone() : nullptr) {}
59 
60  // When T is Any or T is not copy-constructible we need to explicitly disable
61  // the forwarding constructor so that the copy constructor gets selected
62  // instead.
63  template <
64  typename T,
65  typename std::enable_if<
68  // We also disable this overload when an `Any` object can be
69  // converted to the parameter type because in that case, this
70  // constructor may combine with that conversion during overload
71  // resolution for determining copy constructibility, and then
72  // when we try to determine copy constructibility below we may
73  // infinitely recurse. This is being evaluated by the standards
74  // committee as a potential DR in `std::any` as well, but we're
75  // going ahead and adopting it to work-around usage of `Any` with
76  // types that need to be implicitly convertible from an `Any`.
78  std::is_copy_constructible<typename std::decay<T>::type>>::value,
79  int>::type = 0>
80  Any(T &&Value) {
81  using U = typename std::decay<T>::type;
82  Storage = llvm::make_unique<StorageImpl<U>>(std::forward<T>(Value));
83  }
84 
85  Any(Any &&Other) : Storage(std::move(Other.Storage)) {}
86 
87  Any &swap(Any &Other) {
88  std::swap(Storage, Other.Storage);
89  return *this;
90  }
91 
92  Any &operator=(Any Other) {
93  Storage = std::move(Other.Storage);
94  return *this;
95  }
96 
97  bool hasValue() const { return !!Storage; }
98 
99  void reset() { Storage.reset(); }
100 
101 private:
102  template <class T> friend T any_cast(const Any &Value);
103  template <class T> friend T any_cast(Any &Value);
104  template <class T> friend T any_cast(Any &&Value);
105  template <class T> friend const T *any_cast(const Any *Value);
106  template <class T> friend T *any_cast(Any *Value);
107  template <typename T> friend bool any_isa(const Any &Value);
108 
109  std::unique_ptr<StorageBase> Storage;
110 };
111 
112 template <typename T> const char Any::TypeId<T>::Id = 0;
113 
114 
115 template <typename T> bool any_isa(const Any &Value) {
116  if (!Value.Storage)
117  return false;
118  using U =
119  typename std::remove_cv<typename std::remove_reference<T>::type>::type;
120  return Value.Storage->id() == &Any::TypeId<U>::Id;
121 }
122 
123 template <class T> T any_cast(const Any &Value) {
124  using U =
125  typename std::remove_cv<typename std::remove_reference<T>::type>::type;
126  return static_cast<T>(*any_cast<U>(&Value));
127 }
128 
129 template <class T> T any_cast(Any &Value) {
130  using U =
131  typename std::remove_cv<typename std::remove_reference<T>::type>::type;
132  return static_cast<T>(*any_cast<U>(&Value));
133 }
134 
135 template <class T> T any_cast(Any &&Value) {
136  using U =
137  typename std::remove_cv<typename std::remove_reference<T>::type>::type;
138  return static_cast<T>(std::move(*any_cast<U>(&Value)));
139 }
140 
141 template <class T> const T *any_cast(const Any *Value) {
142  using U =
143  typename std::remove_cv<typename std::remove_reference<T>::type>::type;
144  assert(Value && any_isa<T>(*Value) && "Bad any cast!");
145  if (!Value || !any_isa<U>(*Value))
146  return nullptr;
147  return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value;
148 }
149 
150 template <class T> T *any_cast(Any *Value) {
151  using U = typename std::decay<T>::type;
152  assert(Value && any_isa<U>(*Value) && "Bad any cast!");
153  if (!Value || !any_isa<U>(*Value))
154  return nullptr;
155  return &static_cast<Any::StorageImpl<U> &>(*Value->Storage).Value;
156 }
157 
158 } // end namespace llvm
159 
160 #endif // LLVM_ADT_ANY_H
Any & operator=(Any Other)
Definition: Any.h:92
Definition: Any.h:27
This class represents lattice values for constants.
Definition: AllocatorList.h:24
bool hasValue() const
Definition: Any.h:97
friend bool any_isa(const Any &Value)
Definition: Any.h:115
Any & swap(Any &Other)
Definition: Any.h:87
Definition: BitVector.h:938
Any()=default
ELFYAML::ELF_STO Other
Definition: ELFYAML.cpp:784
#define T
void reset()
Definition: Any.h:99
friend T any_cast(const Any &Value)
Definition: Any.h:123
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:941
Any(T &&Value)
Definition: Any.h:80
Any(const Any &Other)
Definition: Any.h:57
Any(Any &&Other)
Definition: Any.h:85
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73