
On Tue, Nov 27, 2012 at 11:05 PM, Andrey Semashev <andrey.semashev@gmail.com
wrote:
On Wed, Nov 28, 2012 at 3:35 AM, Jeffrey Lee Hellrung, Jr. <jeffrey.hellrung@gmail.com> 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.
Right, I just hadn't installed 1.52.0 yet; this macro transition seemed to be only halfway done in 1.51.0.
#include <cstddef>
namespace boost {
typedef std::nullptr_t nullptr_t;
} // namespace boost
#else // #ifndef BOOST_NO_NULLPTR
#include <ostream>
<iosfwd>, please.
Ah, need to overload on basic_ostream for that to work, of course.
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; }
I guess this could be simplified slightly with just typedef (nullptr_t::*_boost_explicit_operator_bool_result_type);
#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.
Right.
} // 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?
You mean template< class T > inline bool operator==(boost::nullptr_t, T * const p) { return 0 == p; } ? Yeah, no dice. - Jeff