tags:

views:

251

answers:

5

The Title pretty much sums up my question. Why can't the following be done to check for a null pointer?

auto_ptr<char> p( some_expression );
// ...
if ( !p )  // error

This must be done instead:

if ( !p.get() ) // OK

Why doesn't auto_ptr<T> simply have operator!() defined?

A: 

Because it doesn't.

Noah Roberts
I see, you're a tautologist.
jball
Well I agree with Noah as it is....
Matthieu M.
+7  A: 

Simply put, it should have operator !() defined. auto_ptr is not a very well designed container. The smart pointers in boost have the operator bool() conversion operator defined which can be negated with operator !(). That will let your if(!p) compile and work as expected.

SilverSun
"`auto_ptr` is not a very well designed container" sums it up quite nicely.
Cogwheel - Matthew Orlando
`auto_ptr` isn't a container. Also why should it have `operator!()` defined? If you're going to claim this, then I think you need to justify this claim. I can't see any inherent reason to define it; it's not as though `if (a.get() == 0)` is unclear or difficult to use.
Charles Bailey
If something is designed to act like a smarter pointer, then its interfaces should resemble a pointer.
Cogwheel - Matthew Orlando
@Charles I suppose container isn't the most accurate word to use. What should I call it?
SilverSun
"class" ;) {need more characters}
Cogwheel - Matthew Orlando
@Cogwheel: If you're looking for a smarter pointer you are not looking for `auto_ptr`. The correct usage of `auto_ptr` is fundamentally different from that of a pointer (e.g. copying) so I don't believe that `auto_ptr` can or should act transparently like a pointer.
Charles Bailey
Well, no use of auto_ptr will be "correct" after the next standard hits, so it'll be moot one of these years ;)
Cogwheel - Matthew Orlando
@Charles, i like how you defend it, but don't you agree that it just sucks? If its usage is different from that of a pointer then its name was incredibly bad chosen.
Johannes Schaub - litb
@litb: I'm afraid I don't agree that `auto_ptr` just sucks. It fills a useful role. It's biggest problems are that that role is not often needed and that it's the only "smart" pointer in C++03 so often people try to use it where it isn't appropriate. Yes, `unique_ptr` will be better but it needs language features that aren't available in C++03 for a reasonably compact implementation.
Charles Bailey
A: 

I suspect because it was expected that passing around auto_ptrs to null would be a rare case, to avoid adding extra interface, and to make it explicit when actually checking for null.

Mark B
Given that auto_ptr::operator= transfers the ownership and sets the source auto_ptr to null, auto_ptr to null can be fairly common.
Pete Kirkham
+13  A: 

Seems to be there was an error in its design. This will be fixed in C++0x. unique_ptr (replacement for auto_ptr) contains explicit operator bool() const;

Quote from new C++ Standard:

The class template auto_ptr is deprecated. [Note: The class template unique_ptr (20.9.10) provides a better solution. —end note ]


Some clarification:
Q: What's wrong with a.get() == 0?
A: Nothing is wrong with a.get()==0, but smart pointers lets you work with them as they were real pointers. Additional operator bool() gives you such a choice. I think, that the real reason for making auto_ptr deprecated is that is has has not intuitive design. But operator bool for unique_ptr in the new Standard means that there are no reasons not to have it.

Kirill V. Lyadvinsky
"Stupid" question: what does `explicit` here means ? I have only ever seen it with constructors.
Matthieu M.
It means the same thing it means for constructors - that the constructor or conversion operator doesn't participate in the implicit conversion dance that occurs when you try to pass an object to a function expecting an arg of a different type
Terry Mahaffey
Sure, `auto_ptr` has been deprecated but why is was it a design error not to have `operator!()`? What's wrong with `a.get() == 0`?
Charles Bailey
Nothing bad with `a.get()==0`, but smart pointers lets you work with them as they were real pointers. Additional `operator bool()` gives you such a choice. I think, that the real reason for making `auto_ptr` deprecated is that is has has not intuitive design. But `operator bool` for `unique_ptr` in new Standard means that there're no reasons not to have it.
Kirill V. Lyadvinsky
It's a valid opinion; perhaps you should add it to your answer. At the moment your answer says it's a design error; it could be updated to say it's a design error because...
Charles Bailey
@Charles as Kirill suggested, it's about giving smart pointers the same public interface that pointers have. That can be important when writing generic code: a.get() would not compile if generic code tried to apply this to a regular pointer.
@stinky472: Fundamentally, smart pointers cannot have the exactly the same public interface as pointers otherwise (by definition) they wouldn't be smart. In particular `auto_ptr` is not designed to be a better pointer, it has an interface that handles transfer of ownership in reliable exception safe manner.
Charles Bailey
@stinky472: I believe that the generic code argument is bogus. You cannot treat an `auto_ptr` as if it were a pointer; if you are writing generic code that can be used with both you have to stick to the operations that have common semantics. As you've now ruled out copying, assignment and destruction you're left with nothing that couldn't be achieved with a function just taking a pointer value and if you have an `auto_ptr` you can safely pass in `get()` to the raw pointer version.
Charles Bailey
@Matthieu: In C++03, only constructors can be `explicit`. Having `explicit` conversion operators is a new C++0x feature (yet another subtle change in C++0x; I didn't know about it until I saw @Terry's comment and thought "what kind of craziness is that?!" But, in fact, he's right :-P).
James McNellis
@Terry/James: Thanks, yet another little change that seems worth it. However how does that affect the syntax ? Does that mean I can do `if (p)` but not `if (!p)` because `!` is a function (unless it's redefined on `unique_ptr`) ?
Matthieu M.
@ Matthieu M, "A conversion function may be explicit (7.1.2), in which case it is only considered as a user-defined conversionfor direct-initialization (8.5). Otherwise, user-defined conversions are not restricted to use in assignmentsand initializations."
Kirill V. Lyadvinsky
+2  A: 

There is an issue with boolean conversion. It allows syntaxes that are nearly always a pain.

There is, luckily, a solution: the Safe Bool idiom.

The problem with a conversion to bool is that implicit conversion is dangerous.

std::auto_ptr<T> p = ..., q = ....;

if (p < q) // uh ?

Therefore, operator bool() const is an abomination. Either you provide an explicit method... or you use the safe bool idiom.

The idea of the idiom is to give you an instance of a type with a pretty minimal subset of operations and almost no case where the implicit conversion will get you into trouble. This is done by using a pointer to member function.

Operations like if (p) and if (!p) then make sense, but if (p < q) will fail to compile.

Read the link thoroughly for the complete solution, and you'll realize why it was a good idea not to have operator bool() const.

Matthieu M.