// 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); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as // published by the Free Software Foundation; either version 3 of the License, // or (at your option) any later version. // // Licensees holding a valid commercial license may use this file in // accordance with the commercial license agreement provided with the software. // // This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. // // $URL$ // $Id$ // SPDX-License-Identifier: LGPL-3.0+ // // // 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() { } #ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE template Object(T && t, private_tag) : obj(new boost::any(std::forward(t))) { } #else template Object(const T&t, private_tag) : obj(new boost::any(t)) { } #endif // implicit constructor from optionals containing variants template Object(const boost::optional< boost::variant >& t) : obj( t ? boost::apply_visitor(Any_from_variant(), *t) : NULL) { } // 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 NULL are only there for Nef... bool operator==(Nullptr_t CGAL_assertion_code(n)) const { CGAL_assertion(n == 0); return empty(); } bool operator!=(Nullptr_t CGAL_assertion_code(n)) const { CGAL_assertion(n == 0); return !empty(); } #endif // CGAL_NO_DEPRECATED_CODE }; #ifndef CGAL_CFG_NO_CPP0X_RVALUE_REFERENCE template inline Object make_object(T && t) { return Object(std::forward(t), Object::private_tag()); } #else template inline Object make_object(const T& t) { return Object(t, Object::private_tag()); } #endif 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 throw() { 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 NULL; } 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