6

I'd like to keep my code compilable both on legacy C++ (C++ code using "NULL") and new C++11 standard (C++ code using "nullptr")

I'm using GCC, but planning to recompile the whole codebase also for VS when I'll finish most important things.

Should I expect both GCC and VS will do something like

#define NULL nullptr

Or Is better I'll do that myself (using of course a different name, where MY_LIB will be replaced by my library suffix)?

#ifndef nullptr
    #define MY_LIB_NULL NULL
#else
    #define MY_LIB_NULL nullptr
#endif

What I want to achieve is code that compiles regardless of wich C++11 features have been implemented or not (and since i'm not using templates, there are very few of them).

For example the keywords "override" and "final" are already done.

MY_LIB_OVERRIDE //macro, defines to "override" if c++11 is present.
MY_LIB_FINAL    //macro, defines to "final" if c++11 is present.

I'm asking the question because I know the "nullptr" question is a bit strange, so maybe just doing the same I already did for override and final, is wrong. Needs opinions about that. Any help is wellcome.

ildjarn
  • 62,044
  • 9
  • 127
  • 211
CoffeDeveloper
  • 7,961
  • 3
  • 35
  • 69
  • seems that some compiler implementors are already defining NULL as "nullptr", so the safest way is to use directly NULL, if nullptr is present it will be used, if nullptr is not present, then NULL is still safe.. so why using "nullptr" if we already have NULL? Or is there the chance that implementors will drop "NULL" (I think highly unprobable) – CoffeDeveloper Dec 02 '12 at 23:44
  • 1
    `#define NULL nullptr` should not be legal, currently, and probably never will be. `NULL` must expand to a integral constant expression with the value zero. – GManNickG Dec 03 '12 at 00:16
  • http://stackoverflow.com/questions/7200674/is-null-defined-as-nullptr-in-c11 , if that is not legal, why are implementors allowed to do that? (i'm not defining "NULL", just want to know If i can assume implementors will do "define NULL nullptr" to keep code using NULL compatible with C++11 or if I must provide an alternative macro with a name different from NULL). Can "NULL" be dropped at all in a future GCC version? (I hope and believe not) – CoffeDeveloper Dec 03 '12 at 00:17
  • 1
    Wow, I'm surprised such a change is allowed; that has the potential to break a ton of code (that code would arguably be "bad" code, but the committee doesn't like to break code regardless). I stand corrected, though. And no, I don't think `NULL` will ever be dropped for the same reason: breaking code, like it or not, is not generally okay to do. – GManNickG Dec 03 '12 at 00:21
  • I see your point. Having NULL defined as nullptr will potentially give troubles when mixing C and C++ code. I guess that will need a check on "_cplusplus" at least.. or maybe I'm wrong... That's why I need a nice and consistent way to make code happy with a unique null pointer type.. Now I have an half idea, I'll wait for more answers and if no one answer i'll put that half idea hoping someone can help me to improve that. – CoffeDeveloper Dec 03 '12 at 00:28
  • Your other option perhaps is to define `nullptr` to `NULL` for compilers that don't support `nullptr`? – Brian L Dec 03 '12 at 00:45
  • i don't think compiler will detect "nullptr" definition since it's a keyword. Infact above example code will not work and MY_LIB_NULL will always be defined as "nullptr" wich gives troubles on older compiler versions. – CoffeDeveloper Dec 03 '12 at 08:29
  • 1
    @DarioOO You can't detect `nullptr` specifically, but you can detect C++11: `#if __cplusplus >= 201103`. –  Dec 03 '12 at 09:00
  • thanks, ther's interesting discussion about that: http://stackoverflow.com/questions/2324658/how-to-determine-the-version-of-the-c-standard-used-by-the-compiler Actually _cplusplus < 201103L (I suppose because Gcc 4.7.2 does not have all c++11 features implemented and so can't be considered 201103L, i guess in few years (optimistically few months) #if __cplusplus >= 201103L will be true. ) – CoffeDeveloper Dec 03 '12 at 09:15
  • 1
    I don't have GCC 4.7 installed on this system, but its value will depend on whether you're compiling with `-std=c++11`/`-std=gnu++11`. Browsing the [GCC source code](http://gcc.gnu.org/git/gitweb.cgi?p=gcc.git;a=blob;f=libcpp/init.c;h=2ec5ecbce11fa200b38bd62b7939b61746682cf3;hb=trunk#l479) online, this is already implemented (although not necessarily for 4.7). –  Dec 03 '12 at 09:21

3 Answers3

4

You could probably create a "false" my_nullptr of type my_nullptr_t the following way:

const class my_nullptr_t
{
    public:

        /* Return 0 for any class pointer */
        template<typename T>
        operator T*() const
        {
            return 0;
        }

        /* Return 0 for any member pointer */
        template<typename T, typename U>
        operator T U::*() const
        {
            return 0;
        }

        /* Safe boolean conversion */
        operator void*() const
        {
            return 0;
        }

    private:

        /* Not allowed to get the address */
        void operator&() const;

} my_nullptr = {};

This works with C++03 and C++11 and should always be safe, whichever C++11 features are implemented. That solution was actually already discussed in this topic that proposed a version of nullptr_t based on the Official proposal.

Community
  • 1
  • 1
Morwenn
  • 21,684
  • 12
  • 93
  • 152
  • I think it should technically have `operator==`, `operator!=`, and `operator bool()`, although code won't use those often. – aschepler Dec 03 '12 at 23:28
  • The `explicit operator bool()` would be great but can't be used unless you already use C++11. t seems that `operator==` and `operator!=` are not needed though: comparison with any pointer works just fine. – Morwenn Dec 03 '12 at 23:37
  • Right, you would only need to overload `operator==` and `operator!=` for when both sides are `my_nullptr_t`. Which is silly, but some template instantiation might do it. – aschepler Dec 03 '12 at 23:41
  • 1
    I carefully looked at the paper with the proposal for nullptr, (n2431.pdf) and already looked the related topic on stackoverflow, so this answer is a duplicate.. The drawbacks of implementing "my_nullptr_t" are worst than just using NULL (end of page 3 of the paper), so I'll use NULL when C++11 is not available, and "nullptr" (the keyword), only when #if __cplusplus >= 201103 (as already suggested by hvd). I'd liked to mark his comment as best answer. but he posted a comment, not an answer. – CoffeDeveloper Dec 09 '12 at 10:45
  • Soory for the duplicate answer then. I discovered the aforementioned topic after having posted this answer. And by the way, I just added an overload of `operator void*() const` for a safe boolean conversion, just for the sake of completeness. – Morwenn Dec 09 '12 at 10:50
1

NULL is a macro that expands to a null pointer constant. It still works just like it used to. Code that has to work with non-C++11 compilers should use NULL.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165
0

I think following will works:

#include <cstddef>

#ifndef MY_LIB_NULL
    #ifndef NULL //check for NULL
        #define MY_LIB_NULL nullptr
    #else
        #define MY_LIB_NULL NULL ///use NULL if present
    #endif
#endif

basically I check for "NULL". wich is a macro and can be checked, until the compiler is shipped with that macro (likely to be), than it's valid using the macro, when compiler will only provides "nullptr" and no longer have NULL then nullptr is used (maybe in a far future, but seems we can happily continue to use NULL!)

I think that's safer than redefining "nullptr" (like most people trying to do)

CoffeDeveloper
  • 7,961
  • 3
  • 35
  • 69
  • `` is required to define the macro `NULL`, so testing for `NULL` will only fail on an egregiously non-conforming implementation. – Pete Becker Dec 03 '12 at 14:20
  • isn't NULL defined in every implementation wich have the cstddef header? – CoffeDeveloper Dec 03 '12 at 14:26
  • Yes, `NULL` is required to be defined in ``, and `` is required to be present for every conforming implementation. – Pete Becker Dec 03 '12 at 14:29
  • so it will be defined for conforming implementation. Non - conforming implementation will just don't compile because NULL was not defined and stuff like ptr = NULL; becomes ptr = nullptr;(and if old c++ code is present nullptr is not a know token by compiler) wich is wanted behaviour (at least in my case, if something is not conforming with at least old C++ code I don't expect to be conforming with C++11) – CoffeDeveloper Dec 03 '12 at 14:33
  • Yes, although I doubt that there's an implementation anywhere that doesn't define `NULL`, although the safest bet is `stddef.h`. This is ancient C stuff. – Pete Becker Dec 03 '12 at 15:00