// This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2015, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_ #define CHAISCRIPT_BOXED_CAST_HELPER_HPP_ #include #include #include "boxed_value.hpp" #include "type_info.hpp" namespace chaiscript { class Type_Conversions; namespace detail { // Cast_Helper_Inner helper classes template T* throw_if_null(T *t) { if (t) return t; throw std::runtime_error("Attempted to dereference null Boxed_Value"); } /// Generic Cast_Helper_Inner, for casting to any type template struct Cast_Helper_Inner { typedef std::reference_wrapper::type > Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { auto p = throw_if_null(ob.get_const_ptr()); return std::cref(*static_cast(p)); } else { throw chaiscript::detail::exception::bad_any_cast(); } } }; template struct Cast_Helper_Inner : Cast_Helper_Inner { }; /// Cast_Helper_Inner for casting to a const & type template struct Cast_Helper_Inner : Cast_Helper_Inner { }; /// Cast_Helper_Inner for casting to a const * type template struct Cast_Helper_Inner { typedef const Result * Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { return static_cast(throw_if_null(ob.get_const_ptr())); } else { throw chaiscript::detail::exception::bad_any_cast(); } } }; /// Cast_Helper_Inner for casting to a * type template struct Cast_Helper_Inner { typedef Result * Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.is_ref()) { return &(ob.get().cast >()).get(); } else { return (ob.get().cast >()).get(); } } }; /// Cast_Helper_Inner for casting to a & type template struct Cast_Helper_Inner { typedef Result& Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result))) { return *(static_cast(throw_if_null(ob.get_ptr()))); } else { throw chaiscript::detail::exception::bad_any_cast(); } } }; /// Cast_Helper_Inner for casting to a std::shared_ptr<> type template struct Cast_Helper_Inner > { typedef std::shared_ptr Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return ob.get().cast >(); } }; /// Cast_Helper_Inner for casting to a std::shared_ptr type template struct Cast_Helper_Inner > { typedef std::shared_ptr Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (!ob.get_type_info().is_const()) { return std::const_pointer_cast(ob.get().cast >()); } else { return ob.get().cast >(); } } }; /// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type template struct Cast_Helper_Inner > : Cast_Helper_Inner > { }; template struct Cast_Helper_Inner &> : Cast_Helper_Inner > { }; /// Cast_Helper_Inner for casting to a const std::shared_ptr & type template struct Cast_Helper_Inner > : Cast_Helper_Inner > { }; template struct Cast_Helper_Inner &> : Cast_Helper_Inner > { }; /// Cast_Helper_Inner for casting to a Boxed_Value type template<> struct Cast_Helper_Inner { typedef const Boxed_Value & Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return ob; } }; /// Cast_Helper_Inner for casting to a Boxed_Value & type template<> struct Cast_Helper_Inner { typedef Boxed_Value& Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return const_cast(ob); } }; /// Cast_Helper_Inner for casting to a const Boxed_Value & type template<> struct Cast_Helper_Inner : Cast_Helper_Inner { }; template<> struct Cast_Helper_Inner : Cast_Helper_Inner { }; /// Cast_Helper_Inner for casting to a std::reference_wrapper type template struct Cast_Helper_Inner > : Cast_Helper_Inner { }; template struct Cast_Helper_Inner > : Cast_Helper_Inner { }; template struct Cast_Helper_Inner &> : Cast_Helper_Inner { }; template struct Cast_Helper_Inner > : Cast_Helper_Inner { }; template struct Cast_Helper_Inner > : Cast_Helper_Inner { }; template struct Cast_Helper_Inner & > : Cast_Helper_Inner { }; /// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner template struct Cast_Helper { typedef typename Cast_Helper_Inner::Result_Type Result_Type; static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) { return Cast_Helper_Inner::cast(ob, t_conversions); } }; } } #endif