diff --git a/doc/conversion.qbk b/doc/conversion.qbk index 6cf1571..47d325d 100644 --- a/doc/conversion.qbk +++ b/doc/conversion.qbk @@ -173,17 +173,17 @@ This includes C++ built-in pointers, `std::shared_ptr`, // Throws: std::bad_cast if ( dynamic_cast(x) == 0 ) // Returns: dynamic_cast(x) template - inline Derived polymorphic_cast(Base* x); + constexpr Derived polymorphic_cast(Base* x); // Effects: assert( dynamic_cast(x) == x ); // Returns: static_cast(x) template - inline Derived polymorphic_downcast(Base* x); + constexpr Derived polymorphic_downcast(Base* x); // Effects: assert( dynamic_cast(&x) == &x ); // Returns: static_cast(x) template - inline Derived polymorphic_downcast(Base& x); + constexpr Derived polymorphic_downcast(Base& x); // Throws: std::bad_cast if ( dynamic_pointer_cast(x) == 0 ) // Returns: dynamic_pointer_cast(x) diff --git a/include/boost/polymorphic_cast.hpp b/include/boost/polymorphic_cast.hpp index ee0c6bb..f6162aa 100644 --- a/include/boost/polymorphic_cast.hpp +++ b/include/boost/polymorphic_cast.hpp @@ -62,6 +62,12 @@ # include # include +#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 - inline Target polymorphic_cast(Source* x) + BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST Target polymorphic_cast(Source* x) { Target tmp = dynamic_cast(x); if ( tmp == 0 ) boost::throw_exception( std::bad_cast() ); @@ -93,7 +99,7 @@ namespace boost // Contributed by Dave Abrahams template - inline Target polymorphic_downcast(Source* x) + BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST Target polymorphic_downcast(Source* x) { BOOST_ASSERT( dynamic_cast(x) == x ); // detect logic error return static_cast(x); @@ -109,7 +115,7 @@ namespace boost // Contributed by Julien Delacroix template - inline typename std::enable_if< + BOOST_CONVERSION_IMPL_CONSTEXPR_DYN_CAST typename std::enable_if< std::is_reference::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 diff --git a/test/cast_test.cpp b/test/cast_test.cpp index 8747397..5998bad 100644 --- a/test/cast_test.cpp +++ b/test/cast_test.cpp @@ -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(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(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(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[] ) {