Boost logo

Boost :

Subject: Re: [boost] [config] Macro for null pointer
From: Eric Niebler (eric_at_[hidden])
Date: 2012-12-05 13:50:41


On 12/5/2012 8:59 AM, Nathan Crookston wrote:
> Andrey Semashev wrote:
>
>> Felipe Magno de Almeida wrote:
>>
>>> Andrey Semashev wrote:
>>>> Eric Niebler wrote:
>>>
>>> [snip]
>>>
>>>>> ... and Microsoft's min/max macros cause no problems because they can
>>>> be
>>>>> disabled with NOMINMAX. :-P
>>>>
>>>> I don't see how this is related. We're not making nullptr a macro, it
>>>> still obeys scoping rules.
>>>
>>> If it is global, then it is all scopes. And it can't even be qualified,
>>> because
>>> nullptr is never used qualified in user code.
>>
>> I find reiterating myself. Yes, it is global but it's not a macro. The
>> global using declaration is optional and can be disabled if there's another
>> global nullptr available (a very slim probability). Other than the global
>> import, it does not conflict with any other implementation (i.e. in another
>> scope).
>>
>> So, is there a use case that is broken with this approach that I'm missing?
>
> I would be concerned if I were using a library (A) which used boost.nullptr
> and another library (B) which shipped its own, potentially at global scope.
>
> I can disable the global using declaration, but if library A is using it
> unqualified, as suggested, then wouldn't I need to update that library's
> code? Or would they be required to check for the disabling macro?

Precisely. Before boost had its min/max guidelines, we used to tell
people to just compile with NOMINMAX when conflicts arose. Then we
learned that some of Microsoft's own Platform SDK headers don't compile
in that configuration. This situation can happen not just for macros but
also for conditionally-defined global variables. Which is why I brought
the example up.

> I wonder if it wouldn't be better to have something like the following:
>
> namespace boost
> {
> namespace detail
> {
> class nullptr_t {...};
> }
>
> #ifdef BOOST_CXX11_NO_NULLPTR
> typedef boost::detail::nullptr_t nullptr_t;
> #else
> typedef std::nullptr_t nullptr_t;
> #endif
>
> namespace
> {
> const boost::detail::nullptr_t nullptr_ = {};
> }
> }//end boost
>
> And user code would use boost::nullptr_ of type boost::nullptr_t.
>
> It's not as nice as using straight nullptr, but I think it will
> interoperate better, since we're not constrained to suggest using it
> unqualified due to the nullptr keyword.

I for one will simply be using 0 in code that needs to be portable. I
don't feel the need for anything fancier.

I might consider using a BOOST_NULLPTR macro if it were defined like this:

#if c++11 // <-- psuedo-code
#define BOOST_NULLPTR nullptr
#else
#define BOOST_NULLPTR 0
#endif

I'm not partial to the above suggestion from Nate because AFAIK there is
no way for a user-defined type to perfectly emulate nullptr, and there
is no migration path to C++11. But it's preferable to putting a nullptr
identifier in the global scope, IMO.

-- 
Eric Niebler
BoostPro Computing
http://www.boostpro.com

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