Topic: An legitimization of auto_ptr_ref


Author: "Andrei Alexandrescu" <andrewalex@hotmail.com>
Date: 2000/08/13
Raw View
Hello,


Summary: According to the Defect Report "127.  auto_ptr<> conversion
issues" on http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html,
auto_ptr_ref does not correctly work inside auto_ptr and must be taken
out at namespace level. This article makes a proposal for
standardizing a little structure that replaces auto_ptr_ref in the
global namespace, and in addition is useful in solving the reference
to reference problem.

Checkpoint: is my understanding of auto_ptr correct? In my
understanding, auto_ptr has a constructor that takes a non-const
reference to another auto_ptr, and a constructor that takes an
auto_ptr_ref by value. Also, auto_ptr has a user-defined conversion to
auto_ptr ref. When initialized from a temporary, the conversion to
auto_ptr_ref and back enter in action. The structure auto_ptr_ref
merely wraps a reference to the source auto_ptr object. I will refer
below to the auto_ptr_ref invention as to "the Colvin/Gibbons trick",
because Bill Gibbons and Greg Colvin invented it.

(I deliberately ignored the template issues like automatic conversions
from auto_ptr<Derived> to auto_ptr<Base>. The basic mechanism remains
the same.)

Okay. Now consider this little structure and its associated helper
function:

template <class T> class by_ref_type {
    T& ref_;
public:
    explicit by_ref_type(T& ref) : ref_(ref) {}
    operator T&() const { return ref_; }
};

template <class T> by_ref_type<T> by_ref(T& val) {
    return by_ref_type<T>(val);
}

This structure can take over the role of auto_ptr ref quite easily:

template <class T>
class auto_ptr
{
    ...
    auto_ptr(auto_ptr&);    // non-const
    auto_ptr(by_ref_type<auto_ptr>); // support the Colvin/Gibbons
    template <class U> operator by_ref_type<auto_ptr<U> >(); // trick
};

Implementing the two functions that support the Colvin/Gibbons trick
is trivial. The conversion operator returns by_ref(*this), and the
constructor extracts the reference using by_ref_type's conversion
operator and manipulates it directly.

So far, nothing too interesting. But I found that by_ref_type is a
more general helper than that. Consider this:

struct A
{
    void Foo(int&);
};

int main()
{
    int i = 10;
    bind2nd(mem_fun(&A::Foo), i); // error
    bind2nd(mem_fun(&A::Foo), by_ref(i)); // WORKS!
}

Interestingly enough, wrapping reference parameter in by_ref calls solves the "reference to reference" problem easily and expressively, in STL and elsewhere. I also found other uses for by_ref in contexts when I wanted to delay a function call, yet that function call needed a reference.

My proposal is to standardize by_ref_t and by_ref. There will be the following benefits:

1. The Colvin/Gibbons trick becomes legit, less obscure, and, most important, easy to reproduce. Programmers that want to implement destructive copy won't have to develop their own *_ref scaffoldings, they can use by_ref_type directly.

2. The reference to reference problem gets a standard, simple solution, using the same scaffolding.

I'd be interested in two things. The first one is whether I've made a fatal mistake somewhere. Is what I wrote above correct? The second one is whether you find it worthy standardizing by_ref_type.


Andrei



---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]