Line data Source code
1 : /* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. 2 : * Use of this file is governed by the BSD 3-clause license that 3 : * can be found in the LICENSE.txt file in the project root. 4 : */ 5 : 6 : // A standard C++ class loosely modeled after boost::Any. 7 : 8 : #pragma once 9 : 10 : #include "antlr4-common.h" 11 : 12 : #ifdef _MSC_VER 13 : #pragma warning(push) 14 : #pragma warning(disable: 4521) // 'antlrcpp::Any': multiple copy constructors specified 15 : #endif 16 : 17 : namespace antlrcpp { 18 : 19 : template<class T> 20 : using StorageType = typename std::decay<T>::type; 21 : 22 : struct ANTLR4CPP_PUBLIC Any 23 : { 24 : bool isNull() const { return _ptr == nullptr; } 25 : bool isNotNull() const { return _ptr != nullptr; } 26 : 27 : Any() : _ptr(nullptr) { 28 : } 29 : 30 0 : Any(Any& that) : _ptr(that.clone()) { 31 : } 32 : 33 : Any(Any&& that) : _ptr(that._ptr) { 34 : that._ptr = nullptr; 35 : } 36 : 37 0 : Any(const Any& that) : _ptr(that.clone()) { 38 : } 39 : 40 : Any(const Any&& that) : _ptr(that.clone()) { 41 : } 42 : 43 : template<typename U> 44 : Any(U&& value) : _ptr(new Derived<StorageType<U>>(std::forward<U>(value))) { 45 : } 46 : 47 : template<class U> 48 : bool is() const { 49 : auto derived = getDerived<U>(false); 50 : 51 : return derived != nullptr; 52 : } 53 : 54 : template<class U> 55 : StorageType<U>& as() { 56 : auto derived = getDerived<U>(true); 57 : 58 : return derived->value; 59 : } 60 : 61 : template<class U> 62 : const StorageType<U>& as() const { 63 : auto derived = getDerived<U>(true); 64 : 65 : return derived->value; 66 : } 67 : 68 : template<class U> 69 : operator U() { 70 : return as<StorageType<U>>(); 71 : } 72 : 73 : template<class U> 74 : operator const U() const { 75 : return as<const StorageType<U>>(); 76 : } 77 : 78 : Any& operator = (const Any& a) { 79 : if (_ptr == a._ptr) 80 : return *this; 81 : 82 : auto old_ptr = _ptr; 83 : _ptr = a.clone(); 84 : 85 : if (old_ptr) 86 : delete old_ptr; 87 : 88 : return *this; 89 : } 90 : 91 0 : Any& operator = (Any&& a) { 92 0 : if (_ptr == a._ptr) 93 : return *this; 94 : 95 0 : std::swap(_ptr, a._ptr); 96 : 97 0 : return *this; 98 : } 99 : 100 : virtual ~Any(); 101 : 102 : virtual bool equals(Any other) const { 103 : return _ptr == other._ptr; 104 : } 105 : 106 : private: 107 : struct Base { 108 : virtual ~Base() {}; 109 : virtual Base* clone() const = 0; 110 : }; 111 : 112 : template<typename T> 113 : struct Derived : Base 114 : { 115 : template<typename U> Derived(U&& value_) : value(std::forward<U>(value_)) { 116 : } 117 : 118 : T value; 119 : 120 : Base* clone() const { 121 : return clone<>(); 122 : } 123 : 124 : private: 125 : template<int N = 0, typename std::enable_if<N == N && std::is_nothrow_copy_constructible<T>::value, int>::type = 0> 126 : Base* clone() const { 127 : return new Derived<T>(value); 128 : } 129 : 130 : template<int N = 0, typename std::enable_if<N == N && !std::is_nothrow_copy_constructible<T>::value, int>::type = 0> 131 : Base* clone() const { 132 : return nullptr; 133 : } 134 : 135 : }; 136 : 137 0 : Base* clone() const 138 : { 139 0 : if (_ptr) 140 0 : return _ptr->clone(); 141 : else 142 : return nullptr; 143 : } 144 : 145 : template<class U> 146 : Derived<StorageType<U>>* getDerived(bool checkCast) const { 147 : typedef StorageType<U> T; 148 : 149 : auto derived = dynamic_cast<Derived<T>*>(_ptr); 150 : 151 : if (checkCast && !derived) 152 : throw std::bad_cast(); 153 : 154 : return derived; 155 : } 156 : 157 : Base *_ptr; 158 : 159 : }; 160 : 161 : template<> inline 162 0 : Any::Any(std::nullptr_t&& ) : _ptr(nullptr) { 163 : } 164 : 165 : 166 : } // namespace antlrcpp 167 : 168 : #ifdef _MSC_VER 169 : #pragma warning(pop) 170 : #endif