From: demarcus_at_hotmail_com@tellus.orb.dotsrc.org   
      
   >> If you read this code, what do you think it does?   
   >>   
   >> CameraMan cm( nullptr );   
   >   
   > I would guess that CameraMan is a pointer or PointerLike (whatever the   
   > latter means in detail).   
   >   
   >> It could mean anything, right?   
   >   
   > In theory: Yes. In practice: I hope not.   
   >   
      
   This is a good example of what different people expects from vague code.   
   You make a clear assumption that this will be a smart pointer. How   
   annoyed won't you be when you discover it's something completely   
   different. At least I tend to become slightly uncomfortable when I have   
   check the documentation for every function call I go through in a   
   less-than-perfect code base.   
      
   Had they at least written   
      
   CameraMan cm( ANGLE_MISSING );   
      
   then I would at least have avoided the worst surprises.   
      
   > I cannot prevent any programmer to assign a special funny/obscure   
   > meaning to what it means that some (user-defined) type CameraMan is   
   > initialized by the std::nullptr_t value. I would *hope* that this type   
   > is indeed something that is related to (smart-)pointers. I would still   
   > not know yet whether it means that CameraMan *is* a pointer-like type or   
   > whether it has to be constructed with a pointer-like type (for whatever   
   > reasons).   
   >   
   >> const struct BadAngleType {} BAD_ANGLE;   
   >> typedef NullNameAdapter AnglePtrNNA;   
   >>   
   >> class CameraMan   
   >> {   
   >> public:   
   >> CameraMan( AnglePtrNNA angle ) : angle_(angle) {}   
   >>   
   >> private:   
   >> int* angle_;   
   >> };   
   >>   
   >> int main()   
   >> {   
   >> int* anglep = new int( 180 );   
   >> CameraMan a( anglep );   
   >> CameraMan b( BAD_ANGLE );   
   >> CameraMan c( nullptr ); // Won't compile. Good!   
   >>   
   >> return 0;   
   >> }   
   >>   
   >> I almost got it to work on a general basis. The only thing I didn't   
   >> manage to solve was the situation if you replace int* with   
   >> std::unique_ptr. (If anyone feels tempted to solve it I would be   
   >> delighted)   
   >   
   > It depends what you mean with "manage to solve". Since std::unique_ptr   
   > is movable but not copyable, it means that you have to provide rvalues   
   > instead of lvalues in situations of assignment or construction. And   
   > obviously the container type (such as CameraMan) would be move-only as   
   > well. If you mean, that your adapted code using your NullNameAdapter   
   > template still does not compile, when you have replaced all occurrences   
   > of int* by std::unique_ptr *plus* the necessary additions of   
   > std::move at the appropriate places, you may consider to replace your   
   > member   
   >   
   > // Conversion operator to be able to return the type   
   > // easily.   
   > operator T&() { return t_; }   
   >   
   > by   
   >   
   > // Conversion operator to be able to return the type   
   > // easily.   
   > operator T&() & { return t_; }   
   > operator T&&() && { return std::move(t_); }   
   >   
   > to provide move-only support (in regard to the hosted type T) to   
   > NullNameAdapter.   
   >   
      
   Impressive! I hadn't even seen that operator syntax before. I will take   
   a look at it. Thanks!   
      
      
   >> My question is; would you all agree that nullptr is a magic number that   
   >> always should be replaced with a label like the following?   
   >> const std::nullptr_t BAD_ANGLE = nullptr;   
   >   
   > I wouldn't recommend this as a general guide-line. Instead I would   
   > recommend to think twice if you consider to give values of type   
   > std::nullptr_t a very different meaning from initializing a pointer-like   
   > thingee. It is unclear to me, why your NullNameAdapter gives   
   > std::nullptr_t values such a special meaning. The hidden assumption is,   
   > that all values *different* from std::nullptr_t would be "reasonable"   
   > initialization values. I see no fundamental reason for this assumption.   
   > So what about wrapping boost::optional in your adapter and reflecting   
   > upon whether boost::none_t should be allowed as an initializer? Why   
   > would this be "good" or "bad"?   
   >   
      
   As I wrote in another post in this thread; my own mistake proves my   
   point that unclear code drains energy. Of course BAD_ANGLE should have   
   been MISSING_ANGLE.   
      
   boost::optional is a good tool, but used as a parameter in a constructor   
   it doesn't stop you from providing nullptr as an argument which will   
   force you to check the documentation to understand /what/ is missing.   
      
      
   Regards,   
   Daniel   
      
      
   --   
    [ See http://www.gotw.ca/resources/clcm.htm for info about ]   
    [ comp.lang.c++.moderated. First time posters: Do this! ]   
      
   --- SoupGate-Win32 v1.05   
    * Origin: you cannot sedate... all the things you hate (1:229/2)   
|