1 | #pragma once |
2 | |
3 | #include <Common/typeid_cast.h> |
4 | |
5 | namespace DB |
6 | { |
7 | |
8 | /* This base class adds public methods: |
9 | * - Derived * as<Derived>() |
10 | * - const Derived * as<Derived>() const |
11 | * - Derived & as<Derived &>() |
12 | * - const Derived & as<Derived &>() const |
13 | */ |
14 | |
15 | template <class Base> |
16 | class TypePromotion |
17 | { |
18 | private: |
19 | /// Need a helper-struct to fight the lack of the function-template partial specialization. |
20 | template <class T, bool is_const, bool is_ref = std::is_reference_v<T>> |
21 | struct CastHelper; |
22 | |
23 | template <class T> |
24 | struct CastHelper<T, false, true> |
25 | { |
26 | auto & value(Base * ptr) { return typeid_cast<T>(*ptr); } |
27 | }; |
28 | |
29 | template <class T> |
30 | struct CastHelper<T, true, true> |
31 | { |
32 | auto & value(const Base * ptr) { return typeid_cast<std::add_lvalue_reference_t<std::add_const_t<std::remove_reference_t<T>>>>(*ptr); } |
33 | }; |
34 | |
35 | template <class T> |
36 | struct CastHelper<T, false, false> |
37 | { |
38 | auto * value(Base * ptr) { return typeid_cast<T *>(ptr); } |
39 | }; |
40 | |
41 | template <class T> |
42 | struct CastHelper<T, true, false> |
43 | { |
44 | auto * value(const Base * ptr) { return typeid_cast<std::add_const_t<T> *>(ptr); } |
45 | }; |
46 | |
47 | public: |
48 | template <class Derived> |
49 | auto as() -> std::invoke_result_t<decltype(&CastHelper<Derived, false>::value), CastHelper<Derived, false>, Base *> |
50 | { |
51 | // TODO: if we do downcast to base type, then just return |this|. |
52 | return CastHelper<Derived, false>().value(static_cast<Base *>(this)); |
53 | } |
54 | |
55 | template <class Derived> |
56 | auto as() const -> std::invoke_result_t<decltype(&CastHelper<Derived, true>::value), CastHelper<Derived, true>, const Base *> |
57 | { |
58 | // TODO: if we do downcast to base type, then just return |this|. |
59 | return CastHelper<Derived, true>().value(static_cast<const Base *>(this)); |
60 | } |
61 | }; |
62 | |
63 | } |
64 | |