X-Git-Url: https://gitweb.ps.run/toc/blobdiff_plain/9f94b672a5dc32da5ad01742bd4e976315a30d9c..c6ad2948bb98d42f8e0883ef82cd14cd2d5eda60:/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/Any.h diff --git a/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/Any.h b/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/Any.h new file mode 100644 index 0000000..468db98 --- /dev/null +++ b/antlr4-cpp-runtime-4.9.2-source/runtime/src/support/Any.h @@ -0,0 +1,170 @@ +/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved. + * Use of this file is governed by the BSD 3-clause license that + * can be found in the LICENSE.txt file in the project root. + */ + +// A standard C++ class loosely modeled after boost::Any. + +#pragma once + +#include "antlr4-common.h" + +#ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable: 4521) // 'antlrcpp::Any': multiple copy constructors specified +#endif + +namespace antlrcpp { + +template + using StorageType = typename std::decay::type; + +struct ANTLR4CPP_PUBLIC Any +{ + bool isNull() const { return _ptr == nullptr; } + bool isNotNull() const { return _ptr != nullptr; } + + Any() : _ptr(nullptr) { + } + + Any(Any& that) : _ptr(that.clone()) { + } + + Any(Any&& that) : _ptr(that._ptr) { + that._ptr = nullptr; + } + + Any(const Any& that) : _ptr(that.clone()) { + } + + Any(const Any&& that) : _ptr(that.clone()) { + } + + template + Any(U&& value) : _ptr(new Derived>(std::forward(value))) { + } + + template + bool is() const { + auto derived = getDerived(false); + + return derived != nullptr; + } + + template + StorageType& as() { + auto derived = getDerived(true); + + return derived->value; + } + + template + const StorageType& as() const { + auto derived = getDerived(true); + + return derived->value; + } + + template + operator U() { + return as>(); + } + + template + operator const U() const { + return as>(); + } + + Any& operator = (const Any& a) { + if (_ptr == a._ptr) + return *this; + + auto * old_ptr = _ptr; + _ptr = a.clone(); + + if (old_ptr) + delete old_ptr; + + return *this; + } + + Any& operator = (Any&& a) { + if (_ptr == a._ptr) + return *this; + + std::swap(_ptr, a._ptr); + + return *this; + } + + virtual ~Any(); + + virtual bool equals(Any other) const { + return _ptr == other._ptr; + } + +private: + struct Base { + virtual ~Base() {}; + virtual Base* clone() const = 0; + }; + + template + struct Derived : Base + { + template Derived(U&& value_) : value(std::forward(value_)) { + } + + T value; + + Base* clone() const { + return clone<>(); + } + + private: + template::value, int>::type = 0> + Base* clone() const { + return new Derived(value); + } + + template::value, int>::type = 0> + Base* clone() const { + return nullptr; + } + + }; + + Base* clone() const + { + if (_ptr) + return _ptr->clone(); + else + return nullptr; + } + + template + Derived>* getDerived(bool checkCast) const { + typedef StorageType T; + + auto derived = dynamic_cast*>(_ptr); + + if (checkCast && !derived) + throw std::bad_cast(); + + return derived; + } + + Base *_ptr; + +}; + + template<> inline + Any::Any(std::nullptr_t&& ) : _ptr(nullptr) { + } + + +} // namespace antlrcpp + +#ifdef _MSC_VER +#pragma warning(pop) +#endif