I would like to understand better the mechanics and the issues behind creating library and I have decided to start from the std::auto_ptr. I am familiar with the syntax and the usage, however I am trying to understand the implementation details. I have implemented my version of the auto_ptr and it looks like this:
#ifndef _AUTO_PTR_H
#define _AUTO_PTR_H
namespace test
{
template<typename T>
class auto_ptr
{
public:
//ctor, dtor, copy ctor and assignment
explicit auto_ptr(T* ptr = 0) throw()
: ptr_(ptr) {}
auto_ptr(auto_ptr& other) throw()
:ptr_(other.release()) {}
auto_ptr<T>& operator=(auto_ptr<T>& other)
{
reset(other.release());
return *this;
}
template<typename U>
auto_ptr<T>& operator=(auto_ptr<U>& other) throw()
{
reset(other.release());
return *this;
}
template<typename U>
auto_ptr(auto_ptr<U>& other) throw()
: ptr_(other.release()) {}
//member
~auto_ptr() throw() { delete ptr_; }
T& operator*() const throw() { return *ptr_; }
T* operator->() const throw() { return ptr_; }
T* get() const throw() { return ptr_; }
T* release() throw()
{
T* temp = ptr_;
ptr_ = 0;
return temp;
}
void reset(T* ptr = 0) throw()
{
if (ptr_ != ptr)
{
delete ptr_;
ptr_ = ptr;
}
}
private:
T* ptr_;
};
}
#endif
My class is doing pretty much the job then I have read this question and it is clear why auto_ptr_ref is there for. However I would like to have an actual example when the auto_ptr behaves differently without add auto_ptr_ref.
My implementation works correctly with this functions:
template <typename T>
test::auto_ptr<T> source()
{
return test::auto_ptr<T>(new T());
}
template <typename T>
void sink(test::auto_ptr<T> bye)
{
}
template <typename T>
void useButNotSink(const test::auto_ptr<T> seeYouLater)
{
std::cout << *seeYouLater << std::endl;
}
With this test program:
test::auto_ptr<double> copyConstructed(source<double>());
std::cout << *copyConstructed << std::endl;
std::cout << copyConstructed.get() << std::endl;
test::auto_ptr<double> assigned(new double(10));
assigned = source<double>();
std::cout << *assigned << std::endl;
std::cout << assigned.get() << std::endl;
*assigned = 2044;
std::cout << *assigned << std::endl;
useButNotSink(assigned);
sink(assigned);
std::cout << assigned.get() << std::endl;
I am sure I am missing something,can you give me an example where the auto_ptr_ref struct and the conversion operators are mandatory to get the correct behaviour?
Thanks