#pragma once #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int BAD_CAST; } } /** 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 std::enable_if_t, To> typeid_cast(From & from) { try { if ((typeid(From) == typeid(To)) || (typeid(from) == typeid(To))) return static_cast(from); } catch (const std::exception & e) { throw DB::Exception(e.what(), DB::ErrorCodes::BAD_CAST); } throw DB::Exception("Bad cast from type " + demangle(typeid(from).name()) + " to " + demangle(typeid(To).name()), DB::ErrorCodes::BAD_CAST); } template std::enable_if_t, To> typeid_cast(From * from) { try { if ((typeid(From) == typeid(std::remove_pointer_t)) || (typeid(*from) == typeid(std::remove_pointer_t))) return static_cast(from); else return nullptr; } catch (const std::exception & e) { throw DB::Exception(e.what(), DB::ErrorCodes::BAD_CAST); } } template std::enable_if_t, To> typeid_cast(const std::shared_ptr & from) { try { if ((typeid(From) == typeid(typename To::element_type)) || (typeid(*from) == typeid(typename To::element_type))) return std::static_pointer_cast(from); else return nullptr; } catch (const std::exception & e) { throw DB::Exception(e.what(), DB::ErrorCodes::BAD_CAST); } }