/* 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