nullptr/__nullptr

 

MSDN has conflicting information about nullptr/__nullptr and /clr:

 

http://msdn.microsoft.com/en-us/library/dd465215(VS.100).aspx says:

The Visual C++ compiler lets you use the nullptr keyword with native code or with managed code. ... The compiler interprets nullptr to be managed code when you use the /clr compiler option, and native code when you do not use the /clr option.

 

Then adds:

The Microsoft-specific __nullptr keyword has the same meaning as nullptr, but it applies to native code only. If you compile native C/C++ code by using the /clr compiler option, the compiler cannot determine whether the nullptr keyword is a native or a managed term. To make your intention clear to the compiler, use the nullptr keyword to specify the managed term, and __nullptr to specify the native term.

 

Highlighted part indicates that compiler cannot determine whether it is native or managed, but the previous paragraph just said it will interpret it as managed.

 

http://msdn.microsoft.com/en-us/library/4ex65770.aspx says the same "cannot determine" thing and then gives an example to contrary:

 

The following sample shows that nullptr can be assigned to a native pointer when you compile with /clr.

// mcpp_nullptr_6.cpp
// compile with: /clr
int main() {
   int * i = 0;
   int * j = nullptr;
}
So what should I expect from all of this? I am guessing that the compiler takes nullptr as managed with /clr,
 because otherwise there wouldn't be a way to say nullptr in managed, and the sample is just an old garbage?
 
Here's how it's supposed to work, and what MSDN should say:
__nullptr is always the Native Nullptr, regardless of whether the compilation is native, /clr, or /clr:pure.
std::nullptr_t is always the Native Nullptr's Type, regardless of whether the compilation is native, /clr, or /clr:pure.  It is defined by <cstddef>.  For good measure (as permitted but not required by C++0x), both <cstddef> and <stddef.h> define both std::nullptr_t and ::nullptr_t.  JonCaves even made the compiler join the fun - it defines std::nullptr_t (but not ::nullptr_t) even in the absence of any headers whatsoever.
nullptr is the Native Nullptr when compiled as native (as required by C++0x).
nullptr is the Managed Nullptr Of Doom when compiled as /clr or /clr:pure (as required by the Necronomicon, 
which is to say C++/CLI).
That said, I don't know how the Managed Nullptr works, except that I've heard that "it doesn't have a type", 
a concept from which my mind recoils in fear.  There's been a little talk of unifying these things, 
but I don't think anybody has figured out what that would involve yet.  When this came up I said:
> Regarding A Tale Of Two Nullptrs, I've heard several times that the problem is that the managed nullptr 
"doesn't have a type", whatever that means, while the native nullptr has a type.  
I don't know what it'd take to unify them (I assume that the native nullptr would have to "win", 
since it cannot be infected with managedness, and conversions to managed stuff would have to be added to make 
up the difference - and too bad for anyone who inspects nullptr closely and is surprised to discover that it 
now has a type - I think all of those words in that order make sense), other than the fact that it 
wasn't obviously simple enough for JonCaves to do in the first place.
> The Iron Nullptr Curtain causes more user suffering than STL suffering, though - 
our only real interaction is in the definition of std::nullptr_t where we simply say decltype(__nullptr).  
In the rest of our implementation, we just use NULL/0 (Dinkumware overwhelmingly prefers 0, as I recall).
 

In this case, perhaps the ambiguity in the docs is a reflection of the thing itself. If nullptr is always
the MNOD when compiled with /clr, then why does the compiler allow int* j to be initialized with it,
as shown in the code example referred to below? I don’t know why the docs say “the compiler cannot determine…”
because at least in these simple initializations it seems to know what to do (converting nullptr to nullptr_t
when the lhs is a native type, regardless of /clr?). But I’m curious what pain this causes or might cause for users.
Is there ever a case where the non-identity of these two things leaks out? If so, then we should really mention that
in the docs.

 

// mcpp_nullptr_6.cpp
// compile with: /clr
int main() {
   int * i = 0;
   int * j = nullptr; //what IS j now?
   int^ k = nullptr; //the same or different?
}
 
 
 
 
 
 
 
 

C:\Temp>type doooooooom.cpp

#include <iostream>

#include <memory>

#include <ostream>

using namespace std;

 

int main() {

    auto sp = make_shared<int *>(nullptr);

    cout << sp.get() << endl;

}

 

C:\Temp>cl /EHsc /nologo /W4 doooooooom.cpp

doooooooom.cpp

 

C:\Temp>doooooooom

00227B2C

 

C:\Temp>cl /clr /nologo /W4 doooooooom.cpp

doooooooom.cpp

doooooooom.cpp(7) : error C2664: 'std::tr1::shared_ptr<_Ty> std::tr1::make_shared<int*,nullptr>(_Arg0 &&)' : cannot conv

ert parameter 1 from 'nullptr' to 'nullptr &&'

        with

        [

            _Ty=int *,

            _Arg0=nullptr

        ]

        nullptr can only be converted to pointer or handle types

doooooooom.cpp(7) : fatal error C1903: unable to recover from previous error(s); stopping compilation





















































posted on 2011-03-02 17:58 Enki 阅读(1274) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿

随笔档案

文章档案

搜索

最新评论

阅读排行榜

评论排行榜