Last active
April 19, 2025 03:13
-
-
Save dk949/55ab7a19955b3161593067eb3837eb20 to your computer and use it in GitHub Desktop.
Provides a more convenient way to work with different kinds of dynamically polymorphic values
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef UT_ASIS | |
#define UT_ASIS | |
#include <memory> | |
#include <type_traits> | |
namespace ut { | |
/** | |
* Try to downcast from reference type `From` to pointer to `To`. | |
* | |
* If cast cannot be performed, returns `nullptr`. | |
* | |
* Preserves constness. | |
*/ | |
template<typename To, typename From> | |
auto as(From &&f) requires( | |
std::has_virtual_destructor_v<std::remove_reference_t<From>> &&std::is_base_of_v<std::remove_reference_t<From>, To>) { | |
using Ret = std::conditional_t<std::is_const_v<std::remove_reference_t<From>>, To const *, To *>; | |
return dynamic_cast<Ret>(&f); | |
} | |
/** | |
* Try to downcast from pointer type `From` to pointer to `To`. | |
* | |
* If cast cannot be performed, returns `nullptr`. | |
* | |
* Preserves constness. | |
*/ | |
template<typename To, typename From> | |
auto as(From *f) requires(std::has_virtual_destructor_v<From> &&std::is_base_of_v<From, To> | |
) { | |
using Ret = std::conditional_t<std::is_const_v<From>, To const *, To *>; | |
return dynamic_cast<Ret>(f); | |
} | |
/** | |
* Try to downcast from `unique_ptr<From>` to pointer to `To`. | |
* | |
* If cast cannot be performed, returns `nullptr`. | |
* | |
* Preserves constness. | |
*/ | |
template<typename To, typename From> | |
auto as(std::unique_ptr<From> const &f) requires(std::has_virtual_destructor_v<From> &&std::is_base_of_v<From, To>) { | |
using Ret = std::conditional_t<std::is_const_v<From>, To const *, To *>; | |
return dynamic_cast<Ret>(f.get()); | |
} | |
/** | |
* Try to downcast from `shared_ptr<From>` to pointer to `To`. | |
* | |
* If cast cannot be performed, returns `nullptr`. | |
* | |
* Preserves constness. | |
*/ | |
template<typename To, typename From> | |
auto as(std::shared_ptr<From> const &f) requires(std::has_virtual_destructor_v<From> &&std::is_base_of_v<From, To>) { | |
using Ret = std::conditional_t<std::is_const_v<From>, To const *, To *>; | |
return dynamic_cast<Ret>(f.get()); | |
} | |
/** | |
* Checks if `From` has dynamic type `To` | |
*/ | |
template<typename To, typename From> | |
bool is(From &&f) { | |
return !!as<To>(std::forward<From>(f)); | |
} | |
} // namespace ut | |
#endif // UT_ASIS |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Provides a more convenient way to work with different kinds of dynamically polymorphic values. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment