Boost logo

Boost :

Subject: Re: [boost] [config] Macro for null pointer
From: Jeffrey Lee Hellrung, Jr. (jeffrey.hellrung_at_[hidden])
Date: 2012-11-27 18:35:44


On Sun, Nov 18, 2012 at 2:03 PM, Jeffrey Lee Hellrung, Jr. <
jeffrey.hellrung_at_[hidden]> wrote:

> On Sun, Nov 18, 2012 at 7:22 AM, Edward Diener <eldiener_at_[hidden]>wrote:
>
>> On 11/16/2012 12:32 AM, Jeffrey Lee Hellrung, Jr. wrote:
>>
>>> On Thu, Nov 15, 2012 at 7:04 PM, Edward Diener <eldiener_at_[hidden]>
>>> **wrote:
>>>
>>> I have found something like this to be helpful, when working with
>>>> multiple
>>>> compilers:
>>>>
>>>> #include <boost/config.hpp>
>>>> #if defined(BOOST_NO_NULLPTR)
>>>> #define BOOST_XXX_NULLPTR 0
>>>> #else
>>>> #define BOOST_XXX_NULLPTR nullptr
>>>> #endif
>>>>
>>>> where XXX is some local name for my own use. And then use
>>>> BOOST_XXX_NULLPTR in places where a null pointer is needed.
>>>>
>>>> Would this be a candidate for a BOOST_NULLPTR macro in the config
>>>> library
>>>> instead ?
>>>>
>>>>
>>> Might it be better to just offer a (albeit imperfect) nullptr emulation
>>> if
>>> not supplied by the compiler? For example, [1].
>>>
>>> - Jeff
>>>
>>> [1] http://en.wikibooks.org/wiki/**More_C%2B%2B_Idioms/nullptr>
>>>
>>
>> I agree that you are right.
>>
>> If the nullptr emulation has less problems than using 0 it would seem
>> worthwhile. That appears to be easily the case. Both are of course
>> imperfect but it appears that a nullptr emulation is far less imperfect.
>> The question then is who is going to do it and support it, given that it
>> will most probably be obsolete in the near future as more compilers
>> implement features of C++11. Unless someone steps up to do it ( and I am
>> not that person due to, for one, already being behind in getting TTI into
>> Boost ) it will not be done and then using 0 is at least a second best
>> solution.
>>
>> In my own current use of nullptr in cross-compiler code for Boost using 0
>> is adequate for my means in the few instances where I am using nullptr. So
>> my suggestion in my OP is adequate for me right now but may well not be
>> adequate for others or for future usage on compilers which do not support
>> nullptr.
>>
>
> I'll post something this week and if it's ultimately decided to be
> included in, e.g., boost/utility, I don't have a problem supporting it.
>

First go at it:

/*** BEGIN NULLPTR DEFINITION ***/

#include <boost/config.hpp>

#ifndef BOOST_NO_NULLPTR

#include <cstddef>

namespace boost
{

typedef std::nullptr_t nullptr_t;

} // namespace boost

#else // #ifndef BOOST_NO_NULLPTR

#include <ostream>

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); }

} // 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).

Also, I only tested this on MSVC9 (for now).

Comments?

- Jeff


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk