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 ]