1#pragma once
2
3#include <type_traits>
4#include <typeinfo>
5#include <typeindex>
6#include <string>
7
8#include <Common/Exception.h>
9#include <common/demangle.h>
10
11
12namespace DB
13{
14 namespace ErrorCodes
15 {
16 extern const int BAD_CAST;
17 }
18}
19
20
21/** Perform static_cast in release build.
22 * Checks type by comparing typeid and throw an exception in debug build.
23 * The exact match of the type is checked. That is, cast to the ancestor will be unsuccessful.
24 */
25template <typename To, typename From>
26To assert_cast(From && from)
27{
28#ifndef NDEBUG
29 try
30 {
31 if constexpr (std::is_pointer_v<To>)
32 {
33 if (typeid(*from) == typeid(std::remove_pointer_t<To>))
34 return static_cast<To>(from);
35 }
36 else
37 {
38 if (typeid(from) == typeid(To))
39 return static_cast<To>(from);
40 }
41 }
42 catch (const std::exception & e)
43 {
44 throw DB::Exception(e.what(), DB::ErrorCodes::BAD_CAST);
45 }
46
47 throw DB::Exception("Bad cast from type " + demangle(typeid(from).name()) + " to " + demangle(typeid(To).name()),
48 DB::ErrorCodes::BAD_CAST);
49#else
50 return static_cast<To>(from);
51#endif
52}
53