Allow using polymorphic_downcast and polymorphic_cast in constexpr (#30)

This commit is contained in:
Antony Polukhin
2025-06-27 20:42:54 +03:00
committed by GitHub
parent 452adac97f
commit b74a4c34cb
3 changed files with 56 additions and 6 deletions

View File

@ -173,17 +173,17 @@ This includes C++ built-in pointers, `std::shared_ptr`,
// Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
// Returns: dynamic_cast<Derived>(x)
template <class Derived, class Base>
inline Derived polymorphic_cast(Base* x);
constexpr Derived polymorphic_cast(Base* x);
// Effects: assert( dynamic_cast<Derived>(x) == x );
// Returns: static_cast<Derived>(x)
template <class Derived, class Base>
inline Derived polymorphic_downcast(Base* x);
constexpr Derived polymorphic_downcast(Base* x);
// Effects: assert( dynamic_cast<Derived>(&x) == &x );
// Returns: static_cast<Derived>(x)
template <class Derived, class Base>
inline Derived polymorphic_downcast(Base& x);
constexpr Derived polymorphic_downcast(Base& x);
// Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 )
// Returns: dynamic_pointer_cast<Derived>(x)

View File

@ -62,6 +62,12 @@
# include <typeinfo>
# include <type_traits>
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
#define BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST constexpr
#else
#define BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST inline
#endif
namespace boost
{
// See the documentation for descriptions of how to choose between
@ -74,7 +80,7 @@ namespace boost
// section 15.8 exercise 1, page 425.
template <class Target, class Source>
inline Target polymorphic_cast(Source* x)
BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST Target polymorphic_cast(Source* x)
{
Target tmp = dynamic_cast<Target>(x);
if ( tmp == 0 ) boost::throw_exception( std::bad_cast() );
@ -93,7 +99,7 @@ namespace boost
// Contributed by Dave Abrahams
template <class Target, class Source>
inline Target polymorphic_downcast(Source* x)
BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST Target polymorphic_downcast(Source* x)
{
BOOST_ASSERT( dynamic_cast<Target>(x) == x ); // detect logic error
return static_cast<Target>(x);
@ -109,7 +115,7 @@ namespace boost
// Contributed by Julien Delacroix
template <class Target, class Source>
inline typename std::enable_if<
BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST typename std::enable_if<
std::is_reference<Target>::value, Target
>::type polymorphic_downcast(Source& x)
{
@ -121,4 +127,6 @@ namespace boost
} // namespace boost
#undef BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST
#endif // BOOST_POLYMORPHIC_CAST_HPP

View File

@ -38,6 +38,48 @@ namespace
};
}
constexpr bool compile_time_polymorphic_cast_check() {
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
Derived derived;
Base* base = &derived;
return polymorphic_cast<Derived*>(base) != nullptr;
#endif
return true;
}
static_assert(
compile_time_polymorphic_cast_check(),
"polymorphic_cast does not work at compile time"
);
constexpr bool compile_time_polymorphic_downcast_check() {
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
Derived derived;
Base* base = &derived;
return polymorphic_downcast<Derived*>(base) != nullptr;
#endif
return true;
}
static_assert(
compile_time_polymorphic_downcast_check(),
"polymorphic_downcast does not work at compile time"
);
constexpr bool compile_time_polymorphic_downcast2_check() {
#if defined(__cpp_constexpr) && __cpp_constexpr >= 201907L
Derived derived;
Base& base = derived;
Derived& derived_again = polymorphic_downcast<Derived&>(base);
(void)derived_again;
#endif
return true;
}
static_assert(
compile_time_polymorphic_downcast2_check(),
"polymorphic_downcast does not work at compile time"
);
int main( int argc, char * argv[] )
{