diff --git a/doc/interprocess.qbk b/doc/interprocess.qbk index efab1d6..56301fd 100644 --- a/doc/interprocess.qbk +++ b/doc/interprocess.qbk @@ -6866,6 +6866,7 @@ thank them: * Fixed bugs: * [@https://github.com/boostorg/interprocess/issues/242 GitHub #242 (['"Cygwin compatibility issues"])]. * [@https://github.com/boostorg/interprocess/issues/247 GitHub #247 (['"destruction of move-constructed map using private_adaptive_pool triggers Assertion"])]. + * [@https://github.com/boostorg/interprocess/issues/252 GitHub #252 (['"[regression] no viable constructor for offset_ptr with clang from 1.87.0"])]. [endsect] diff --git a/include/boost/interprocess/offset_ptr.hpp b/include/boost/interprocess/offset_ptr.hpp index 6addcf8..1a71ffc 100644 --- a/include/boost/interprocess/offset_ptr.hpp +++ b/include/boost/interprocess/offset_ptr.hpp @@ -251,6 +251,25 @@ namespace ipcdetail { , Ret> {}; + template + struct is_ptr_constructible; + + template + struct is_ptr_constructible + { + private: + template static U get(); + + template + static yes_type test( typename enable_if_c< sizeof( new U*(get()) ) != 0, int >::type ); + + template + static no_type test(...); + + public: + static const bool value = sizeof(test(0)) == sizeof(yes_type); + }; + } //namespace ipcdetail { #endif //#ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED @@ -356,6 +375,20 @@ class offset_ptr : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) {} + //!Constructor from other offset_ptr. Only takes part in overload resolution + //!if PointedType* is constructible from T2* other than via a conversion (e.g. cast to a derived class). Never throws. + template + BOOST_INTERPROCESS_FORCEINLINE explicit offset_ptr(const offset_ptr &ptr + #ifndef BOOST_INTERPROCESS_DOXYGEN_INVOKED + , typename ipcdetail::enable_if_c< + !::boost::move_detail::is_convertible::value && + ipcdetail::is_ptr_constructible::value + >::type * = 0 + #endif + ) BOOST_NOEXCEPT + : internal(ipcdetail::offset_ptr_to_offset(static_cast(ptr.get()), this)) + {} + #endif //!Emulates static_cast operator. diff --git a/test/offset_ptr_test.cpp b/test/offset_ptr_test.cpp index b38b8f3..8b72103 100644 --- a/test/offset_ptr_test.cpp +++ b/test/offset_ptr_test.cpp @@ -411,24 +411,27 @@ void test_cast() pcvvoid_t pcvvoid = pvoid; pcvvoid = pvvoid; - //Test valid static_cast conversions - pint = static_pointer_cast(pvoid); - pcint = static_pointer_cast(pcvoid); - pvint = static_pointer_cast(pvoid); - pcvint = static_pointer_cast(pvoid); + //Test valid static_cast conversions required by Allocator::pointer + //requirements (void_pointer -> pointer, const_void_pointer -> const_pointer) + pint = static_cast(pvoid); + pcint = static_cast(pcvoid); BOOST_TEST(pint == pvoid); BOOST_TEST(pcint == pint); - BOOST_TEST(pvint == pint); - BOOST_TEST(pcvint == pint); - //Test valid static_cast conversions + //Test valid static_pointer_cast conversions { pint = static_pointer_cast(pvoid); pcint = static_pointer_cast(pcvoid); pvint = static_pointer_cast(pvoid); pcvint = static_pointer_cast(pvoid); + BOOST_TEST(pint == pvoid); + BOOST_TEST(pcint == pcvoid); + BOOST_TEST(pcint == pint); + BOOST_TEST(pvint == pint); + BOOST_TEST(pcvint == pint); + Derived d; offset_ptr pd(&d); offset_ptr pb; @@ -450,7 +453,7 @@ void test_cast() BOOST_TEST(pb3.get() == static_cast(pd3.get())); } - //Test valid const_cast conversions + //Test valid const_pointer_cast conversions { pint = const_pointer_cast(pcint); pint = const_pointer_cast(pvint); @@ -462,14 +465,14 @@ void test_cast() pcint = const_pointer_cast(pvint); pcint = const_pointer_cast(pcvint); - //Test valid reinterpret_cast conversions + //Test valid reinterpret_pointer_cast conversions pint = reinterpret_pointer_cast(pvoid); pcint = reinterpret_pointer_cast(pcvoid); pvint = reinterpret_pointer_cast(pvoid); pcvint = reinterpret_pointer_cast(pvoid); } - //Test valid dynamic_cast conversions + //Test valid dynamic_pointer_cast conversions { { Derived3 d3;