// Copyright (c) 2000 // Utrecht University (The Netherlands), // ETH Zurich (Switzerland), // INRIA Sophia-Antipolis (France), // Max-Planck-Institute Saarbruecken (Germany), // and Tel-Aviv University (Israel). All rights reserved. // // This file is part of CGAL (www.cgal.org) // // $URL: https://github.com/CGAL/cgal/blob/v5.1/STL_Extension/include/CGAL/Object.h $ // $Id: Object.h bcf8409 2020-06-23T18:50:20+02:00 Laurent Rineau // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // // Author(s) : Stefan Schirra // Andreas Fabri // Geert-Jan Giezeman // Michael Seel // Sylvain Pion #ifndef CGAL_OBJECT_H #define CGAL_OBJECT_H #include #include #include #include #include #include #include namespace CGAL { class Object { boost::shared_ptr obj; // returns an any pointer from a variant struct Any_from_variant : public boost::static_visitor { template boost::any* operator()(const T& t) const { return new boost::any(t); } }; template friend const T* object_cast(const Object * o); template friend T object_cast(const Object & o); typedef void (Object::*bool_type)() const; void this_type_does_not_support_comparisons() const {} public: struct private_tag{}; Object() : obj() { } template Object(T && t, private_tag) : obj(new boost::any(std::forward(t))) { } // implicit constructor from optionals containing variants template Object(const boost::optional< boost::variant >& t) : obj( t ? boost::apply_visitor(Any_from_variant(), *t) : nullptr) { } // implicit constructor from variants template Object(const boost::variant& v) : obj(boost::apply_visitor(Any_from_variant(), v)) { } template bool assign(T &t) const { if(obj) { #ifdef CGAL_USE_ANY_BAD_CAST try { t = boost::any_cast(*obj); return true; } catch(...) { return false; } #else const T* res = boost::any_cast(&(*obj)); if (res){ t=*res; return true; } return false; #endif } else { return false; } } bool empty() const { return !obj; } // is_empty() is kept for backward compatibility. // empty() was introduced for consistency with e.g. std::vector::empty(). bool is_empty() const { return empty(); } // safe-bool conversion operator bool_type() const { return empty() == false ? &Object::this_type_does_not_support_comparisons : 0; } template bool is() const { return obj && boost::any_cast(obj.get()); } const std::type_info & type() const { if(obj) return obj->type(); else return typeid(void); } #ifndef CGAL_NO_DEPRECATED_CODE // The comparisons with nullptr are only there for Nef... bool operator==(std::nullptr_t /*CGAL_assertion_code(n)*/) const { /*CGAL_assertion(n == 0);*/ return empty(); } bool operator!=(std::nullptr_t /*CGAL_assertion_code(n)*/) const { /*CGAL_assertion(n == 0);*/ return !empty(); } #endif // CGAL_NO_DEPRECATED_CODE }; template inline Object make_object(T && t) { return Object(std::forward(t), Object::private_tag()); } template inline bool assign(T& t, const Object& o) { return o.assign(t); } struct Bad_object_cast : public std::bad_cast { virtual const char * what() const noexcept { return "CGAL::bad_object_cast: " "failed conversion using CGAL::object_cast"; } }; template inline const T * object_cast(const Object * o) { if(o->obj) return boost::any_cast((o->obj).get()); else return nullptr; } template inline T object_cast(const Object & o) { if(!o.obj) throw Bad_object_cast(); const T * result = boost::any_cast((o.obj).get()); if (!result) throw Bad_object_cast(); return *result; } } //namespace CGAL #endif // CGAL_OBJECT_H