[core] [addressof.hpp] [addressof_test2.cpp] ISO C++ says that these are ambiguous
It looks like he following code fragment from boost/core/addressof.hpp (latest trunk version) violates ISO C++ overloading rules: template<class T> struct addressof_impl { static BOOST_FORCEINLINE T * f( T & v, long ) { return reinterpret_cast<T*>( &const_cast<char&>(reinterpret_cast<const volatile char &>(v))); } static BOOST_FORCEINLINE T * f( T * v, int ) { return v; } }; As a result, libs/core/test/addressof_test2.cpp fails to compile with Oracle Studio 12.4 C++ compiler while gcc-4.8.2 produces just warning here. It's easy to reproduce that behavior of both compilers with 26 lines test case listed below: gcc -c t.cc t.cc:7:33: warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second: [enabled by default] return addressof_impl<T>::f(v,0); ^ CC -c t.cc "t.cc", line 7: Error: Overloading ambiguity between "static addressof_impl<convertible2>::f(convertible2&, long)" and "static addressof_impl<convertible2>::f(convertible2*, int)". t.cc ==================================== template<class T> struct addressof_impl{ static T *f(T &v,long){} static T *f(T *v,int){} }; template<class T> T *addressof(T &v){ return addressof_impl<T>::f(v,0); } template<class T> void scalar_test(T* =0){ T *px=new T(); T &x =*px; (addressof(x)==px)? 1 : 0; } class convertible{ public: convertible(int=0){} }; class convertible2{ public: convertible2(int=0){} operator convertible2 *()const{ return 0; } }; void foo(){ scalar_test<convertible>(); scalar_test<convertible2>(); } ============================== It would be nice if boost/core/addressof.hpp file will be changed somehow to fit the proper ISO C++ requirements. Sergey
Sergey Sprogis wrote: ...
It looks like he following code fragment from boost/core/addressof.hpp (latest trunk version) violates ISO C++ overloading rules: ... As a result, libs/core/test/addressof_test2.cpp fails to compile with Oracle Studio 12.4 C++ compiler...
That's probably because of the __SUNPRO_CC workaround at addressof.hpp line 110: #if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC ) return boost::detail::addressof_impl<T>::f( v, 0 ); #else return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 ); #endif I assume that defined( __SUNPRO_CC ) needs to be changed to defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, < something ) but it's been a while since we stopped testing on this compiler so I don't know what 'something' must be. It should be set to the earliest version that doesn't need the workaround, but the current value of __SUNPRO_CC will also work.
On Thu, Dec 25, 2014 at 6:01 AM, Peter Dimov <lists@pdimov.com> wrote:
Sergey Sprogis wrote: ...
It looks like he following code fragment from boost/core/addressof.hpp (latest trunk version) violates ISO C++ overloading rules:
...
As a result, libs/core/test/addressof_test2.cpp fails to compile with Oracle Studio 12.4 C++ compiler...
That's probably because of the __SUNPRO_CC workaround at addressof.hpp line 110:
#if (defined( __BORLANDC__ ) && BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x610 ) ) ) || defined( __SUNPRO_CC )
return boost::detail::addressof_impl<T>::f( v, 0 );
#else
return boost::detail::addressof_impl<T>::f( boost::detail::addr_impl_ref<T>( v ), 0 );
#endif
I assume that defined( __SUNPRO_CC ) needs to be changed to
defined( __SUNPRO_CC ) && BOOST_WORKAROUND( __SUNPRO_CC, < something )
but it's been a while since we stopped testing on this compiler so I don't know what 'something' must be. It should be set to the earliest version that doesn't need the workaround, but the current value of __SUNPRO_CC will also work.
Maybe we'd better make this overload differently. I'm thinking about something like: return boost::detail::addressof_impl<T>::f( v, type<T>() ); for all compilers.
participants (3)
-
Andrey Semashev
-
Peter Dimov
-
Sergey Sprogis