"Aaron" == Aaron W LaFramboise
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