/* * type_index without RTTI * * Copyright frickiericker 2016. * Distributed under the Boost Software License, Version 1.0. * * Permission is hereby granted, free of charge, to any person or organization * obtaining a copy of the software and accompanying documentation covered by * this license (the "Software") to use, reproduce, display, distribute, * execute, and transmit the Software, and to prepare derivative works of the * Software, and to permit third-parties to whom the Software is furnished to * do so, all subject to the following: * * The copyright notices in the Software and this entire statement, including * the above license grant, this restriction and the following disclaimer, * must be included in all copies of the Software, in whole or in part, and * all derivative works of the Software, unless such copies or derivative * works are solely in the form of machine-executable object code generated by * a source language processor. * * 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #include namespace ext { /** * Dummy type for tag-dispatching. */ template struct tag_type {}; /** * A value of tag_type. */ template constexpr tag_type tag{}; /** * A type_index implementation without RTTI. */ struct type_index { /** * Creates a type_index object for the specified type. */ template type_index(tag_type) noexcept : hash_code_{index} { } /** * Returns the hash code. */ std::size_t hash_code() const noexcept { return hash_code_; } private: /** * Unique integral index associated to template type argument. */ template static std::size_t const index; /** * Global counter for generating index values. */ static std::size_t& counter() noexcept { static std::size_t counter_; return counter_; } private: std::size_t hash_code_; }; template std::size_t const type_index::index = type_index::counter()++; /** * Creates a type_index object for the specified type. * * Equivalent to `ext::type_index{ext::tag}`. */ template type_index make_type_index() noexcept { return tag; } inline bool operator==(type_index const& a, type_index const& b) noexcept { return a.hash_code() == b.hash_code(); } inline bool operator!=(type_index const& a, type_index const& b) noexcept { return !(a == b); } inline bool operator<(type_index const& a, type_index const& b) noexcept { return a.hash_code() < b.hash_code(); } inline bool operator<=(type_index const& a, type_index const& b) noexcept { return a.hash_code() <= b.hash_code(); } inline bool operator>(type_index const& a, type_index const& b) noexcept { return !(a <= b); } inline bool operator>=(type_index const& a, type_index const& b) noexcept { return !(a < b); } } template <> struct std::hash { using argument_type = ext::type_index; using result_type = std::size_t; result_type operator()(argument_type const& t) const noexcept { return t.hash_code(); } };