#pragma once #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int LOGICAL_ERROR; } } /** Checks type by comparing typeid. * The exact match of the type is checked. That is, cast to the ancestor will be unsuccessful. * In the rest, behaves like a dynamic_cast. */ template requires std::is_reference_v To typeid_cast(From & from) noexcept(false) { if ((typeid(From) == typeid(To)) || (typeid(from) == typeid(To))) return static_cast(from); throw DB::Exception(DB::ErrorCodes::LOGICAL_ERROR, "Bad cast from type {} to {}", demangle(typeid(from).name()), demangle(typeid(To).name())); } template requires std::is_pointer_v To typeid_cast(From * from) noexcept { if ((typeid(From) == typeid(std::remove_pointer_t)) || (from && typeid(*from) == typeid(std::remove_pointer_t))) return static_cast(from); return nullptr; } namespace detail { template struct is_shared_ptr : std::false_type { }; template struct is_shared_ptr> : std::true_type { }; template inline constexpr bool is_shared_ptr_v = is_shared_ptr::value; } template requires detail::is_shared_ptr_v To typeid_cast(const std::shared_ptr & from) noexcept { if ((typeid(From) == typeid(typename To::element_type)) || (from && typeid(*from) == typeid(typename To::element_type))) return std::static_pointer_cast(from); return nullptr; }