21

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?

Paul J. Lucas
  • 6,895
  • 6
  • 44
  • 88

4 Answers4

21

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
  • 97,037
  • 24
  • 136
  • 212
  • "Stupid" question: what does `explicit` here means ? I have only ever seen it with constructors. – Matthieu M. Jun 30 '10 at 17:27
  • 3
    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 Jun 30 '10 at 17:33
  • 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`? – CB Bailey Jun 30 '10 at 17:49
  • 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 Jun 30 '10 at 18:17
  • 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... – CB Bailey Jun 30 '10 at 20:24
  • @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 Jul 01 '10 at 02:34
  • 3
    @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. – CB Bailey Jul 01 '10 at 06:23
  • 1
    @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. – CB Bailey Jul 01 '10 at 06:25
  • 1
    @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 Jul 02 '10 at 05:28
  • @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. Jul 02 '10 at 06:01
  • @ Matthieu M, "A conversion function may be explicit (7.1.2), in which case it is only considered as a user-defined conversion for direct-initialization (8.5). Otherwise, user-defined conversions are not restricted to use in assignments and initializations." – Kirill V. Lyadvinsky Jul 02 '10 at 06:18
8

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.

Nick Strupat
  • 4,928
  • 4
  • 44
  • 56
  • 9
    "`auto_ptr` is not a very well designed container" sums it up quite nicely. – Cogwheel Jun 30 '10 at 17:00
  • 3
    `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. – CB Bailey Jun 30 '10 at 17:02
  • 3
    If something is designed to act like a smarter pointer, then its interfaces should resemble a pointer. – Cogwheel Jun 30 '10 at 17:07
  • @Charles I suppose container isn't the most accurate word to use. What should I call it? – Nick Strupat Jun 30 '10 at 17:09
  • "class" ;) {need more characters} – Cogwheel Jun 30 '10 at 17:11
  • @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. – CB Bailey Jun 30 '10 at 17:11
  • Well, no use of auto_ptr will be "correct" after the next standard hits, so it'll be moot one of these years ;) – Cogwheel Jun 30 '10 at 17:13
  • 5
    @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 Jun 30 '10 at 17:17
  • @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. – CB Bailey Jun 30 '10 at 17:41
5

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.
  • 287,565
  • 48
  • 449
  • 722
0

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
  • 95,107
  • 10
  • 109
  • 188
  • 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 Jun 30 '10 at 17:08