Subject: Re: [boost] [config] Macro for null pointer
From: Andrey Semashev (andrey.semashev_at_[hidden])
Date: 2012-11-28 02:05:52


On Wed, Nov 28, 2012 at 3:35 AM, Jeffrey Lee Hellrung, Jr.
<jeffrey.hellrung_at_[hidden]> wrote:
>
> First go at it:
>
> /*** BEGIN NULLPTR DEFINITION ***/
>
> #include <boost/config.hpp>
>
> #ifndef BOOST_NO_NULLPTR

I believe, the actual macros for C++11 features start with
BOOST_NO_CXX11_ (e.g. BOOST_NO_CXX11_NULLPTR). The ones without CXX11
are deprecated.

> #include <cstddef>
>
> namespace boost
> {
>
> typedef std::nullptr_t nullptr_t;
>
> } // namespace boost
>
> #else // #ifndef BOOST_NO_NULLPTR
>
> #include <ostream>

<iosfwd>, please.

> namespace boost
> {
>
> struct nullptr_t
> {
> template< class T >
> operator T * () const
> { return static_cast< T * >(0); }
>
> template< class T, class C >
> operator T C:: * () const
> { return static_cast< T C:: * >(0); }
>
> #ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
>
> explicit operator bool () { return false; }
>
> #else // #ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
>
> private:
> struct _boost_explicit_operator_bool_struct { };
> typedef int
> (_boost_explicit_operator_bool_struct::*_boost_explicit_operator_bool_result_type);
> public:
> operator _boost_explicit_operator_bool_result_type () const { return 0; }
>
> #endif // #ifndef BOOST_NO_EXPLICIT_CONVERSION_OPERATORS
>
> // Must be public in order for nullptr_t to be POD.
> void * _boost_nullptr_sizeof;
>
> #ifndef BOOST_NO_DELETED_FUNCTIONS
> void operator & () const = delete;
> #else // #ifndef BOOST_NO_DELETED_FUNCTIONS
> private: void operator & () const;
> #endif // #ifndef BOOST_NO_DELETED_FUNCTIONS
> };
>
> boost::nullptr_t const nullptr = { 0 };
>
> inline bool operator==(boost::nullptr_t, boost::nullptr_t) { return true; }
> inline bool operator!=(boost::nullptr_t, boost::nullptr_t) { return false; }
>
> inline std::ostream &
> operator<<(std::ostream & o, boost::nullptr_t)
> { return o << static_cast< void * >(0); }

I think, this is better:

template< typename CharT, typename TraitsT >
inline std::basic_ostream< CharT, TraitsT >& operator<<
(std::basic_ostream< CharT, TraitsT >& strm, boost::nullptr_t)
{
  o << static_cast< void * >(0);
  return o;
}

It will also not require basic_ostream to be defined.

> } // namespace boost
>
> using boost::nullptr;
>
> #endif // #ifndef BOOST_NO_NULLPTR
>
> /*** END NULLPTR DEFINITION ***/
>
> #include <cassert>
>
> #include <boost/implicit_cast.hpp>
> #include <boost/static_assert.hpp>
>
> struct X { };
>
> int main(int argc, char * argv[])
> {
> BOOST_STATIC_ASSERT( sizeof( nullptr ) == sizeof( void * ) );
> assert(!static_cast< bool >(nullptr));
> assert(!nullptr);
> assert(boost::implicit_cast< void * >(nullptr) == 0);
> assert(boost::implicit_cast< int * >(nullptr) == 0);
> assert(boost::implicit_cast< int X::* >(nullptr) == 0);
> //assert(nullptr == static_cast< void * >(0));
> //assert(nullptr != &argc);
> return 0;
> }
>
> Unfortunately, the assertions that are commented out in main trigger an ICE
> on MSVC9 (yeah, big surprise); it's possible I did something wrong, but in
> the event that I didn't, if we can find a workaround to get such
> expressions to work, that'd be great (I tried explicitly defining
> operator== and operator!= out-of-line, and that didn't help).

Will it help if you also define templated comparison operators with pointers?