Boost logo

Boost Users :

From: Joerg Faschingbauer (jfasch_at_[hidden])
Date: 2004-02-05 02:39:11


>>>>> "Aaron" == Aaron W LaFramboise <aaronblue6_at_[hidden]> writes:

Aaron> I recently converted a portion of a medium-sized project from
Aaron> loki::Smart_Ptr to boost::shared_ptr (primarily for weak_ptr support),
Aaron> and almost everything worked out of the box, except:
Aaron> boost: template<class Y> explicit shared_ptr <#constructors>(Y * p);
Aaron> loki: SmartPtr(const StoredType& p)

Aaron> In other words, code like this stopped working:
Aaron> some_smart_ptr<int> my_function() {
Aaron> return new int; // error: conversion from `int*' to non-scalar type
Aaron> `boost::shared_ptr<int>'
Aaron> // requested
Aaron> }

Aaron> Even when I adopt the convention to convert the return value to the
Aaron> smart pointer type such as with "return some_smart_ptr<int>(new int)",
Aaron> returning a null pointer as 'zero' doesn't work:
Aaron> some_smart_ptr<int> my_function() {
Aaron> return some_smart_ptr<int>(0); // error: no matching function for
Aaron> call to
Aaron> // `boost::shared_ptr<int>::shared_ptr(int)'
Aaron> }

Aaron> I've worked around this by simply using "return some_smart_ptr<int>();".

Aaron> However, I feel somewhat strongly that this sort of usage is
Aaron> unnecessarily ugly, and confuses the meaning of the code unnecessarily.
Aaron> More importantly, it causes smart pointers to behave differently from
Aaron> ordinary pointers, which is undesirable, as it requires the user (who
Aaron> may not know or care anything about the smart pointer, or even know that
Aaron> it is one, depending on a module's implementation and documentation) to
Aaron> have to learn and use and debug additional semantics.

Aaron> So my question follows. I understand that there are very good reasons
Aaron> for disallowing automatic conversion from a smart pointer, but why
Aaron> disallow automatic conversion to the smart pointer type also? If there
Aaron> are strong reasons for this, would it be reasonable to document this
Aaron> somewhere in the shared_ptr documentation? If not, is this particular
Aaron> aspect of shared_ptr possibly subject to discussion or change in the future?

This is intentional. Consider the following code; using_func() calls
func() with a plain int*, and the int that the pointer points to is on
the stack.

void func(int* p) {
     // whatever
}

void using_func() {
    int i;
    func(&i);
}

Now consider somebody changes func() to take a shared_ptr<> instead of
the plain int*.

void func(shared_ptr<int> p) {
     // whatever
}

If automatic conversion was allowed, the code would still compile. The
compiler would generate a temporary shared_ptr<int> before calling
func(). In other words,

void using_func() {
    int i;
    func(&i);
}

would actually be

void using_func() {
    int i;
    int* ip = &i;
    shared_ptr<int> temporary(ip);
    func(temporary);
}

Now this is fatal because temporary's destructor is run at the end of
using_func(). The destructor will see that it is the last instance
that references the pointer, and will delete the int instance - which
is on the stack.

Without automatic conversion, the compiler would barf and using_func()
would have to be fixed.

Joerg


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net