541. shared_ptr template assignment and void

Section: 20.3.2.2 [util.smartptr.shared], 99 [tr.util.smartptr.shared] Status: CD1 Submitter: Martin Sebor Opened: 2005-10-16 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [util.smartptr.shared].

View all issues with CD1 status.

Discussion:

Is the void specialization of the template assignment operator taking a shared_ptr<void> as an argument supposed be well-formed?

I.e., is this snippet well-formed:

shared_ptr<void> p;
p.operator=<void>(p);

Gcc complains about auto_ptr<void>::operator*() returning a reference to void. I suspect it's because shared_ptr has two template assignment operators, one of which takes auto_ptr, and the auto_ptr template gets implicitly instantiated in the process of overload resolution.

The only way I see around it is to do the same trick with auto_ptr<void> operator*() as with the same operator in shared_ptr<void>.

PS Strangely enough, the EDG front end doesn't mind the code, even though in a small test case (below) I can reproduce the error with it as well.

template <class T>
struct A { T& operator*() { return *(T*)0; } };

template <class T>
struct B {
    void operator= (const B&) { }
    template <class U>
    void operator= (const B<U>&) { }
    template <class U>
    void operator= (const A<U>&) { }
};

int main ()
{
    B<void> b;
    b.operator=<void>(b);
}

Proposed resolution:

In [lib.memory] change:

template<class X> class auto_ptr;
template<> class auto_ptr<void>;

In [lib.auto.ptr]/2 add the following before the last closing brace:

template<> class auto_ptr<void>
{
public:
    typedef void element_type;
};