Why doesn't auto_ptr<T> have operator!() defined?
Asked Answered
M

4

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?

Maag answered 30/6, 2010 at 16:51 Comment(1)
The question https://mcmap.net/q/660056/-unique_ptr-boost-equivalent/427532 is somewhat related.Transpire
G
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.

Gustin answered 30/6, 2010 at 17:1 Comment(11)
"Stupid" question: what does explicit here means ? I have only ever seen it with constructors.Bolter
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 typeGuacin
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?Guddle
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.Gustin
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...Guddle
@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.Cautionary
@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.Guddle
@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.Guddle
@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).Antherozoid
@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) ?Bolter
@ 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."Gustin
S
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.

Spender answered 30/6, 2010 at 16:59 Comment(9)
"auto_ptr is not a very well designed container" sums it up quite nicely.Couperin
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.Guddle
If something is designed to act like a smarter pointer, then its interfaces should resemble a pointer.Couperin
@Charles I suppose container isn't the most accurate word to use. What should I call it?Spender
"class" ;) {need more characters}Couperin
@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.Guddle
Well, no use of auto_ptr will be "correct" after the next standard hits, so it'll be moot one of these years ;)Couperin
@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.Salomie
@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.Guddle
B
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.

Bolter answered 30/6, 2010 at 17:24 Comment(0)
O
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.

Oneupmanship answered 30/6, 2010 at 17:1 Comment(1)
Given that auto_ptr::operator= transfers the ownership and sets the source auto_ptr to null, auto_ptr to null can be fairly common.Bedpan

© 2022 - 2024 — McMap. All rights reserved.