Topic: Global conversion function names / type casts (templates!) ...
Author: maxtal@Physics.usyd.edu.au (John Max Skaller)
Date: 1995/08/15 Raw View
In article <DD1MI7.C8H.0.-s@cs.vu.nl>, ctv <ctv@cs.vu.nl> wrote:
>
>Operator overloading can be used to implement so called smart
>pointers. Operator "=", "->", etcetera member functions allow
>these smart pointers to be used in (almost) the same way as real
>pointers.
>
>How to mimic real-pointer-like casts when the pointers are actually
>smart pointers ?
Member templates:
template<class T> class Smart {
T *data;
public:
template<class Q>
Smart(Smart<Q> const &arg) {
data = arg.data; // conversion!
}
..
};
struct Base {};
struct Derived : Base {};
Smart<Derived> pd = new Derived;
Smart<Base> = bd; // Smart pointer conversion!
Smart<Derived> bad = pb; // INSTANTIATION FAILS!
Note in the last line the conversion is CORRECT -- there's
no error here, the error occurs instantiating the
member template. If the body isn't visible you'd not
find out until link time.
--
JOHN (MAX) SKALLER, INTERNET:maxtal@suphys.physics.su.oz.au
Maxtal Pty Ltd,
81A Glebe Point Rd, GLEBE Mem: SA IT/9/22,SC22/WG21
NSW 2037, AUSTRALIA Phone: 61-2-566-2189
---
[ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
Author: ctv@cs.vu.nl (ctv)
Date: 1995/08/09 Raw View
Operator overloading can be used to implement so called smart
pointers. Operator "=", "->", etcetera member functions allow
these smart pointers to be used in (almost) the same way as real
pointers.
How to mimic real-pointer-like casts when the pointers are actually
smart pointers ?
Given the smart pointer template class as sketched in the second
code fragment below, I would like to have a conversion (template)
function as depicted in the first code fragment.
To what extent does this first fragment violate the current C++
definition:
1) Is it allowed to have global (i.e. non-class member) cast
functions (operator ConversionFunctionName() ) ?
2) Usually (?) different instantiations of the same template
function are based on differences in their parameters: what
I would like to have is that class names as well as template
class names can be used to define a generic (and user verified)
conversion function framework like it is sketched below in:
"template<class To, class From>" What motivation makes it
unreasonable to expect that not only the parameters can be
"parameterized" but also the function name because it is a
user defined (template) class name ?
3) In which ways does this sketch violate the current C++ definition ?
(at least, the 5 different C++ compilers I use don't accept
(several slightly different implementations of) this example).
Suggestions for an elegant solution ? Of course, it's possible
to define an explicit template function with a name that's not
based on a template class name, however that's not the sort of
solution I'm looking for ....
Example:
class c1; class c2;
ptr<c1> p1; ptr<c2> p2; // smart pointers p1, p2 to
// instances of c1, c2
// See code fragment 1 for:
p2 = ptr<c2> (p1); // function notation
// or:
p2 = (ptr<c2>) p1; // cast notation
Thanks for your help,
-- Cees Visser
========= ========= ========= ========= ========= =========
Code fragment 1:
========= ========= ========= ========= ========= =========
template<class To, class From> ::operator ptr<To> (ptr<From>& from)
{
ptr<To> to;
// run-time checks ...
to.ptr_ = (To *) from.ptr_ ;
return to;
}
========= ========= ========= ========= ========= =========
Code fragment 2:
========= ========= ========= ========= ========= =========
template<class T> class ptr {
private:
T *ptr_; /* real object pointer */
void incr_refc (T* tp) {
// ...
}
void decr_refc (T* tp) {
// ...
}
public:
ptr (void) {
ptr_ = 0;
}
ptr (const ptr& obj) {
ptr_ = obj.ptr_;
incr_refc (ptr_);
}
ptr (T *t) {
ptr_ = t;
incr_refc (ptr_);
}
~ptr (void) {
// ...
}
/* ptr assignment: */
void operator = (ptr& obj) {
decr_refc (ptr_);
ptr_ = obj.ptr_;
incr_refc (ptr_);
return /* not *this */ ;
}
/* null ptr assignment: */
void operator = (void *null_ptr) {
decr_refc (ptr_);
verify (null_ptr == NULL);
ptr_ = 0;
return /* not *this */ ;
}
T* operator -> () {
verify (ptr_ != 0);
return ptr_;
}
/* dereference */
T& operator * () {
verify (ptr_ != 0);
return *ptr_ ;
}
int operator == (ptr& obj) {
return ptr_ == obj.ptr_;
}
int operator != (ptr& obj) {
return ptr_ != obj.ptr_;
}
friend template<class T, class F> ::operator ptr<T>(ptr<F> f);
};