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 ) // Throws: std::bad_cast if ( dynamic_cast<Derived>(x) == 0 )
// Returns: dynamic_cast<Derived>(x) // Returns: dynamic_cast<Derived>(x)
template <class Derived, class Base> template <class Derived, class Base>
inline Derived polymorphic_cast(Base* x); constexpr Derived polymorphic_cast(Base* x);
// Effects: assert( dynamic_cast<Derived>(x) == x ); // Effects: assert( dynamic_cast<Derived>(x) == x );
// Returns: static_cast<Derived>(x) // Returns: static_cast<Derived>(x)
template <class Derived, class Base> template <class Derived, class Base>
inline Derived polymorphic_downcast(Base* x); constexpr Derived polymorphic_downcast(Base* x);
// Effects: assert( dynamic_cast<Derived>(&x) == &x ); // Effects: assert( dynamic_cast<Derived>(&x) == &x );
// Returns: static_cast<Derived>(x) // Returns: static_cast<Derived>(x)
template <class Derived, class Base> 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 ) // Throws: std::bad_cast if ( dynamic_pointer_cast<Derived>(x) == 0 )
// Returns: dynamic_pointer_cast<Derived>(x) // Returns: dynamic_pointer_cast<Derived>(x)

View File

@@ -62,6 +62,12 @@
# include <typeinfo> # include <typeinfo>
# include <type_traits> # 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 namespace boost
{ {
// See the documentation for descriptions of how to choose between // See the documentation for descriptions of how to choose between
@@ -74,7 +80,7 @@ namespace boost
// section 15.8 exercise 1, page 425. // section 15.8 exercise 1, page 425.
template <class Target, class Source> 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); Target tmp = dynamic_cast<Target>(x);
if ( tmp == 0 ) boost::throw_exception( std::bad_cast() ); if ( tmp == 0 ) boost::throw_exception( std::bad_cast() );
@@ -93,7 +99,7 @@ namespace boost
// Contributed by Dave Abrahams // Contributed by Dave Abrahams
template <class Target, class Source> 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 BOOST_ASSERT( dynamic_cast<Target>(x) == x ); // detect logic error
return static_cast<Target>(x); return static_cast<Target>(x);
@@ -109,7 +115,7 @@ namespace boost
// Contributed by Julien Delacroix // Contributed by Julien Delacroix
template <class Target, class Source> 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 std::is_reference<Target>::value, Target
>::type polymorphic_downcast(Source& x) >::type polymorphic_downcast(Source& x)
{ {
@@ -121,4 +127,6 @@ namespace boost
} // namespace boost } // namespace boost
#undef BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST
#endif // BOOST_POLYMORPHIC_CAST_HPP #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[] ) int main( int argc, char * argv[] )
{ {