#pragma once #include namespace DB { /* This base class adds public methods: * - Derived * as() * - const Derived * as() const * - Derived & as() * - const Derived & as() const */ template class TypePromotion { private: /// Need a helper-struct to fight the lack of the function-template partial specialization. template > struct CastHelper; template struct CastHelper { auto & value(Base * ptr) { return typeid_cast(*ptr); } }; template struct CastHelper { auto & value(const Base * ptr) { return typeid_cast>>>(*ptr); } }; template struct CastHelper { auto * value(Base * ptr) { return typeid_cast(ptr); } }; template struct CastHelper { auto * value(const Base * ptr) { return typeid_cast *>(ptr); } }; public: template auto as() -> std::invoke_result_t::value), CastHelper, Base *> { // TODO: if we do downcast to base type, then just return |this|. return CastHelper().value(static_cast(this)); } template auto as() const -> std::invoke_result_t::value), CastHelper, const Base *> { // TODO: if we do downcast to base type, then just return |this|. return CastHelper().value(static_cast(this)); } }; }