Last active
August 29, 2015 14:21
-
-
Save Jules-Baratoux/c588728d3fda32ccdc5f to your computer and use it in GitHub Desktop.
Homework #5 – auto_ptr
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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