Skip to content

Instantly share code, notes, and snippets.

@Jules-Baratoux
Last active August 29, 2015 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jules-Baratoux/c588728d3fda32ccdc5f to your computer and use it in GitHub Desktop.
Save Jules-Baratoux/c588728d3fda32ccdc5f to your computer and use it in GitHub Desktop.
Homework #5 – auto_ptr
#include <cstdlib>
#include <cassert>
#include <typeinfo>
#include "auto_ptr.hh"
int main(int argc, char const *argv[])
{
struct X {};
struct Y : public X {};
auto_ptr<X>::tests::typedefs();
auto_ptr<X>::tests::constructor_default();
auto_ptr<X>::tests::constructor_value();
auto_ptr<X>::tests::constructor_copy();
auto_ptr<Y>::tests::constructor_copy<X>();
auto_ptr<X>::tests::destructor();
auto_ptr<X>::tests::get();
auto_ptr<X>::tests::dereference();
auto_ptr<X>::tests::dereference_member();
auto_ptr<X>::tests::assign();
auto_ptr<X>::tests::assign<Y>();
auto_ptr<X>::tests::release();
auto_ptr<X>::tests::reset();
return EXIT_SUCCESS;
}
#include <cassert>
#include <memory>
#include "informer.hh"
using debug::deleted;
template <typename X>
struct auto_ptr
{
typedef X element_type;
// Constructors
explicit auto_ptr (element_type* pointer = nullptr) throw()
: internal(pointer)
{
}
auto_ptr(auto_ptr& source) throw()
: internal(source.release())
{
}
template <typename Y>
auto_ptr(auto_ptr<Y>& source) throw()
: internal(source.release())
{
}
// Access
element_type* get() const throw()
{
return internal;
}
element_type& operator*() const throw()
{
assert(internal != nullptr);
return *internal;
}
element_type* operator->() const throw()
{
assert(internal != nullptr);
return internal;
}
template<typename Y>
operator auto_ptr<Y>() throw()
{
return auto_ptr<Y>(this->release());
}
// Assignment
auto_ptr& operator=(auto_ptr& rhs) throw()
{
reset(rhs.release());
return *this;
}
template <typename Y>
auto_ptr& operator=(auto_ptr<Y>& rhs) throw()
{
reset(rhs.release());
return *this;
}
// Release & Reset
element_type* release() throw()
{
element_type* tmp = internal;
internal = nullptr;
return tmp;
}
void reset(element_type* source = nullptr) throw()
{
if (source != internal)
{
delete internal;
internal = source;
}
}
bool operator==(const element_type* pointer) const
{
return internal == pointer;
}
// Destructor
~auto_ptr() throw()
{
delete internal;
}
struct tests
{
static void typedefs()
{
assert(typeid(auto_ptr::element_type) == typeid(X));
}
static void constructor_default()
{
auto_ptr pointer;
assert(pointer == nullptr);
}
static void constructor_value()
{
auto pointer = new element_type;
auto_ptr auto_ptr(pointer);
assert(auto_ptr == pointer);
}
static void constructor_copy()
{
{
auto pointer = new element_type;
auto_ptr copy(pointer);
assert(copy == pointer);
}
{
auto pointer = new element_type;
auto_ptr source(pointer);
auto_ptr copy(source);
assert(copy == pointer);
assert(source == nullptr);
}
}
template <typename Y>
static void constructor_copy()
{
{
auto pointer = new X;
auto_ptr<X> source(pointer);
auto_ptr<Y> copy(source);
// assert((void*)copy == (void*)pointer);
assert(source == nullptr);
}
}
static void destructor()
{
auto pointer = new debug::informer<element_type>;
{
auto_ptr<debug::informer<element_type> > auto_ptr(pointer);
assert(deleted(pointer) == false);
}
assert(deleted(pointer) == true);
}
static void get()
{
{
const auto_ptr auto_ptr;
assert(auto_ptr == nullptr);
}
{
auto pointer = new element_type;
const auto_ptr auto_ptr(pointer);
assert(auto_ptr == pointer);
}
}
static void dereference()
{
auto pointer = new element_type;
const auto_ptr auto_ptr(pointer);
assert(&*auto_ptr == pointer);
}
static void dereference_member()
{
struct object
{
X member;
};
auto pointer = new object;
const auto_ptr<object> auto_ptr(pointer);
assert(&auto_ptr->member == &pointer->member);
}
static void assign()
{
auto pointer1 = new element_type;
auto pointer2 = new element_type;
{
auto_ptr auto_ptr0;
auto_ptr auto_ptr1(pointer1);
auto_ptr auto_ptr2(pointer2);
assert(auto_ptr0 == nullptr);
auto_ptr0 = auto_ptr1;
assert(auto_ptr0 == pointer1);
assert(auto_ptr1 == nullptr);
auto_ptr2 = auto_ptr0;
assert(auto_ptr2 == pointer1);
assert(auto_ptr0 == nullptr);
}
assert(deleted(pointer1) == true);
assert(deleted(pointer2) == true);
}
template <typename Y>
static void assign()
{
auto pointer1 = new X;
auto pointer2 = new Y;
{
auto_ptr<X> auto_ptr1(pointer1);
auto_ptr<Y> auto_ptr2(pointer2);
auto_ptr1 = auto_ptr2;
assert(auto_ptr1 == pointer2);
assert(auto_ptr2 == nullptr);
}
assert(deleted(pointer1) == true);
assert(deleted(pointer2) == true);
}
static void release()
{
auto pointer = new element_type;
auto_ptr auto_ptr(pointer);
delete auto_ptr.release();
assert(auto_ptr == nullptr);
}
static void reset()
{
auto pointer0 = new debug::informer<element_type>;
auto pointer1 = new debug::informer<element_type>;
auto pointer2 = new debug::informer<element_type>;
{
auto_ptr<debug::informer<element_type> > auto_ptr(pointer0);
auto_ptr.reset();
}
{
auto_ptr<debug::informer<element_type> > auto_ptr(pointer1);
auto_ptr.reset(pointer2);
assert(auto_ptr == pointer2);
assert(deleted(pointer1) == true);
}
assert(deleted(pointer0) == true);
assert(deleted(pointer2) == true);
}
};
private:
element_type* internal;
};
#pragma once
#include <cstdlib>
#include <cassert>
#include <new>
#include <set>
using std::set;
namespace debug
{
static set<const void*> informer_pointers;
bool deleted(const void* ptr)
{
return informer_pointers.find(ptr) == informer_pointers.end();
}
template <typename type>
struct informer
{
type internal;
informer() : internal()
{
}
informer(const type&& value) : internal(value)
{
}
informer(const type& value) : internal(value)
{
}
operator type&()
{
return internal;
}
static void* operator new(std::size_t sz)
{
auto pointer = ::operator new(sz);
const auto inserted = informer_pointers.insert(pointer);
assert(inserted.second);
return pointer;
}
static void operator delete(void* ptr)
{
informer_pointers.erase(ptr);
::operator delete(ptr);
}
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment