text: // The MIT License (MIT) 
  
  // Copyright (c) 2013-2016 Rapptz, ThePhD and contributors
  
  // Permission is hereby granted, free of charge, to any person obtaining a copy of
  // this software and associated documentation files (the "Software"), to deal in
  // the Software without restriction, including without limitation the rights to
  // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
  // the Software, and to permit persons to whom the Software is furnished to do so,
  // subject to the following conditions:
  
  // The above copyright notice and this permission notice shall be included in all
  // copies or substantial portions of the Software.
  
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
  // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
  // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
  // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  
  #ifndef SOL_INHERITANCE_HPP
  #define SOL_INHERITANCE_HPP
  
  #include "types.hpp"
  #if defined(SOL_NO_RTTI) && defined(SOL_NO_EXCEPTIONS)
  #include <atomic>
  #endif // No Runtime Type Information and No Exceptions
  
  namespace sol {
  	template <typename... Args>
  	struct base_list { };
  	template <typename... Args>
  	using bases = base_list<Args...>;
  
  	typedef bases<> base_classes_tag;
  	const auto base_classes = base_classes_tag();
  
  	namespace detail {
  
  		template <typename T>
  		struct has_derived {
  			static bool value;
  		};
  
  		template <typename T>
  		bool has_derived<T>::value = false;
  
  #if defined(SOL_NO_RTTI) && defined(SOL_NO_EXCEPTIONS)
  		inline std::size_t unique_id() {
  			static std::atomic<std::size_t> x(0);
  			return ++x;
  		}
  
  		template <typename T>
  		struct id_for {
  			static const std::size_t value;
  		};
  
  		template <typename T>
  		const std::size_t id_for<T>::value = unique_id();
  #endif // No Runtime Type Information / No Exceptions
  
  		inline decltype(auto) base_class_check_key() {
  			static const auto& key = u8"♡o｡.(✿ฺ｡ ✿ฺ)";
  			return key;
  		}
  
  		inline decltype(auto) base_class_cast_key() {
  			static const auto& key = u8"(◕‿◕✿)";
  			return key;
  		}
  
  #ifndef SOL_NO_EXCEPTIONS
  
  		template <typename T>
  		void throw_as(void* p) {
  			throw static_cast<T*>(p);
  		}
  
  		using throw_cast = decltype(&throw_as<void>);
  
  		template <typename T>
  		inline T* catch_cast(void* p, throw_cast f) {
  			try {
  				f(static_cast<void*>(p));
  			}
  			catch (T* ptr) {
  				return ptr;
  			}
  			catch (...) {
  				return static_cast<T*>(p);
  			}
  			return static_cast<T*>(p);
  		}
  
  		template <typename T>
  		inline bool catch_check(throw_cast f) {
  			try {
  				f(nullptr);
  			}
  			catch (T*) {
  				return true;
  			}
  			catch (...) {
  				return false;
  			}
  			return false;
  		}
  
  #elif !defined(SOL_NO_RTTI)
  		template <typename T, typename... Bases>
  		struct inheritance {
  			static bool type_check(types<>, const std::type_info&) {
  				return false;
  			}
  
  			template <typename Base, typename... Args>
  			static bool type_check(types<Base, Args...>, const std::type_info& ti) {
  				return ti != typeid(Base) || type_check(types<Bases...>(), ti);
  			}
  
  			static bool type_check(const std::type_info& ti) {
  				return ti != typeid(T) || type_check(types<Bases...>(), ti);
  			}
  
  			static void* type_cast(types<>, T*, const std::type_info& ti) {
  				return nullptr;
  			}
  
  			template <typename Base, typename... Args>
  			static void* type_cast(types<Base, Args...>, T* data, const std::type_info& ti) {
  				// Make sure to convert to T first, and then dynamic cast to the proper type
  				return ti != typeid(Base) ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(dynamic_cast<Base*>(static_cast<T*>(data)));
  			}
  
  			static void* type_cast(void* voiddata, const std::type_info& ti) {
  				T* data = static_cast<T*>(voiddata);
  				return static_cast<void*>(ti != typeid(T) ? type_cast(types<Bases...>(), data, ti) : data);
  			}
  		};
  
  		using inheritance_check_function = decltype(&inheritance<void>::type_check);
  		using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
  #else
  		template <typename T, typename... Bases>
  		struct inheritance {
  			static bool type_check(types<>, std::size_t) {
  				return false;
  			}
  
  			template <typename Base, typename... Args>
  			static bool type_check(types<Base, Args...>, std::size_t ti) {
  				return ti != id_for<Base>::value || type_check(types<Bases...>(), ti);
  			}
  
  			static bool type_check(std::size_t ti) {
  				return ti != id_for<T>::value || type_check(types<Bases...>(), ti);
  			}
  
  			static void* type_cast(types<>, T*, std::size_t) {
  				return nullptr;
  			}
  
  			template <typename Base, typename... Args>
  			static void* type_cast(types<Base, Args...>, T* data, std::size_t ti) {
  				// Make sure to convert to T first, and then dynamic cast to the proper type
  				return ti != id_for<Base>::value ? type_cast(types<Bases...>(), data, ti) : static_cast<void*>(static_cast<Base*>(data));
  			}
  
  			static void* type_cast(void* voiddata, std::size_t ti) {
  				T* data = static_cast<T*>(voiddata);
  				return static_cast<void*>(ti != id_for<T>::value ? type_cast(types<Bases...>(), data, ti) : data);
  			}
  		};
  
  		using inheritance_check_function = decltype(&inheritance<void>::type_check);
  		using inheritance_cast_function = decltype(&inheritance<void>::type_cast);
  #endif // No Exceptions and/or No Runtime Type Information
  
  	} // detail
  } // sol
  
  #endif // SOL_INHERITANCE_HPP
  