Skip to content
Snippets Groups Projects
Commit 1b1941aa authored by Jan Trávníček's avatar Jan Trávníček
Browse files

add vector_ptr, fix shared_ptr, refactor

parent 6c8e7496
No related branches found
No related tags found
No related merge requests found
#ifndef __CLONE_HEADER_WRAPPER_
#define __CLONE_HEADER_WRAPPER_
#include "type_traits"
#include "extensions/clone.hpp"
#endif /* __CLONE_HEADER_WRAPPER_ */
/*
* clone.hpp
*
* Created on: Apr 1, 2013
* Author: Jan Travnicek
*/
#ifndef CLONE_HPP_
#define CLONE_HPP_
namespace std {
template<class T> struct has_clone {
typedef char (&Yes)[1];
typedef char (&No)[2];
template<class U>
static Yes test(U * data, typename std::enable_if< std::is_pointer<decltype(data->clone())>::value>::type * = 0);
static No test(...);
static const bool value = sizeof(Yes) == sizeof(has_clone::test((typename std::remove_reference<T>::type*)0));
};
template<class T, typename std::enable_if< ! std::has_clone<T>::value >::type* = nullptr>
T* clone(const T* tmp) {
return new T(*tmp);
}
template<class T, typename std::enable_if< std::has_clone<T>::value >::type* = nullptr>
T* clone(const T* tmp) {
return tmp->clone();
}
} /* namespace std */
#endif /* CLONE_HPP_ */
......@@ -99,17 +99,9 @@ private:
 
T* tmp = m_Data;
detach( );
attach(clone(tmp));
}
template<class R = T, typename std::enable_if< ! std::is_abstract<R>::value >::type* = nullptr>
T* clone(T* tmp) {
return new T(*tmp);
}
template<class R = T, typename std::enable_if< std::is_abstract<R>::value >::type* = nullptr>
T* clone(T* tmp) {
return tmp->clone();
tmp = std::clone(tmp);
tmp->m_UseCount = 0;
attach(tmp);
}
 
T* m_Data;
......@@ -215,17 +207,7 @@ private:
 
typename cow_shared_ptr<T>::cow_shared_ptr_data* tmp = m_Data;
detach( );
attach(new cow_shared_ptr_data(clone(tmp)));
}
template<class R = T, typename std::enable_if< ! std::is_abstract<R>::value >::type* = nullptr>
T* clone(typename cow_shared_ptr<T>::cow_shared_ptr_data* tmp) {
return new T(*(tmp->m_Data));
}
template<class R = T, typename std::enable_if< std::is_abstract<R>::value >::type* = nullptr>
T* clone(typename cow_shared_ptr<T>::cow_shared_ptr_data* tmp) {
return tmp->m_Data->clone();
attach(new cow_shared_ptr_data(std::clone(tmp->m_Data)));
}
 
cow_shared_ptr_data * m_Data;
......
......@@ -63,7 +63,6 @@ public:
typedef Iterator iterator_type;
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
typedef typename iterator_traits<Iterator>::value_type value_type;
typedef typename iterator_traits<Iterator>::difference_type difference_type;
typedef Iterator pointer;
typedef value_type&& reference;
 
......@@ -73,10 +72,10 @@ public:
explicit set_move_iterator (Iterator it) : current(it) {
}
 
template <class Iter> set_move_iterator (const set_move_iterator<Iter>& it) : current(it.current) {
set_move_iterator (const set_move_iterator<Iterator>& it) : current(it.current) {
}
 
template <class Iter> set_move_iterator& operator= (const set_move_iterator<Iter>& it) {
set_move_iterator& operator= (const set_move_iterator<Iterator>& it) {
current = it.current;
}
 
......
......@@ -10,6 +10,158 @@
 
namespace std {
 
template <class Iterator>
class ptr_vector_iterator {
Iterator current;
public:
typedef Iterator iterator_type;
typedef typename iterator_traits<Iterator>::iterator_category iterator_category;
typedef typename iterator_traits<Iterator>::value_type value_type;
typedef Iterator pointer;
typedef typename std::remove_pointer<value_type>::type& reference;
explicit ptr_vector_iterator() {
}
explicit ptr_vector_iterator (Iterator it) : current(it) {
}
ptr_vector_iterator (const ptr_vector_iterator<Iterator>& it) : current(it.current) {
}
ptr_vector_iterator& operator= (const ptr_vector_iterator<Iterator>& it) {
current = it.current;
}
iterator_type base() const {
return current;
}
pointer operator->() const {
return *current;
}
reference operator*() const {
return **current;
}
ptr_vector_iterator& operator++() {
++current;
return *this;
}
ptr_vector_iterator& operator--() {
--current;
return *this;
}
ptr_vector_iterator& operator++(int) {
ptr_vector_iterator temp = *this;
++current;
return temp;
}
ptr_vector_iterator& operator--(int) {
ptr_vector_iterator temp = *this;
--current;
return temp;
}
bool operator== (const ptr_vector_iterator<Iterator>& other) {
return this->current == other.current;
}
bool operator!= (const ptr_vector_iterator<Iterator>& other) {
return ! ( *this == other );
}
};
template<class Iterator>
ptr_vector_iterator<Iterator> make_ptr_vector_iterator (Iterator it) {
return ptr_vector_iterator<Iterator>(it);
}
template<class T>
class ptr_vector {
vector<T*> data;
public:
ptr_vector() {}
ptr_vector(const ptr_vector<T>& other) {
data.reserve(other.size());
for(T* ptr : other.data) {
data.push_back(std::clone(ptr));
}
}
ptr_vector(ptr_vector<T>&& other) noexcept {
std::swap(this->data, other.data);
}
ptr_vector<T>& operator=(const ptr_vector<T>& other) {
if(this == *other) return *this;
*this = ptr_vector(other);
return *this;
}
~ptr_vector() noexcept {
for(T* elem : data) {
delete elem;
}
}
ptr_vector<T>& operator=(ptr_vector<T>&& other) noexcept {
std::swap(this->data, other.data);
return *this;
}
T& operator[]( int n ) {
return *data[n];
}
const T& operator[]( int n ) const {
return *data[n];
}
void push_back(T* elem) {
data.push_back(elem);
}
unsigned size() const {
return data.size();
}
ptr_vector_iterator<typename std::vector<T*>::iterator> begin() {
return make_ptr_vector_iterator(data.begin());
}
ptr_vector_iterator<typename std::vector<T*>::iterator> end() {
return make_ptr_vector_iterator(data.end());
}
ptr_vector_iterator<typename std::vector<T*>::const_iterator> begin() const {
return make_ptr_vector_iterator(data.cbegin());
}
ptr_vector_iterator<typename std::vector<T*>::const_iterator> end() const {
return make_ptr_vector_iterator(data.cend());
}
ptr_vector_iterator<typename std::vector<T*>::const_iterator> cbegin() {
return make_ptr_vector_iterator(data.cbegin());
}
ptr_vector_iterator<typename std::vector<T*>::const_iterator> cend() {
return make_ptr_vector_iterator(data.cend());
}
};
template< class T >
std::ostream& operator<<(std::ostream& out, const std::vector<T>& vector) {
out << "[";
......@@ -40,6 +192,21 @@ struct compare<vector<T>> {
}
};
 
template<class T>
struct compare<ptr_vector<T>> {
int operator()(const ptr_vector<T>& first, const ptr_vector<T>& second) const {
if(first.size() < second.size()) return -1;
if(first.size() > second.size()) return 1;
compare<T> comp;
for(auto iterF = first.begin(), iterS = second.begin(); iterF != first.end(); iterF++, iterS++) {
int res = comp(*iterF, *iterS);
if(res != 0) return res;
}
return 0;
}
};
} /* namespace std */
 
#endif /* __VECTOR_HPP_ */
......
......@@ -3,6 +3,7 @@
 
#include <bits/../memory>
#include <type_traits>
#include "clone"
#include "extensions/memory.hpp"
 
#endif /* __MEMORY_HEADER_WRAPPER_ */
......@@ -4,6 +4,7 @@
#include <bits/../vector>
#include <ostream>
#include "compare"
#include "clone"
#include "extensions/vector.hpp"
 
#endif /* __VECTOR_HEADER_WRAPPER_ */
......
......@@ -70,3 +70,17 @@ void SharedPtrTest::testSharedPtr2() {
 
}
 
void SharedPtrTest::testSharedPtr3() {
std::cow_shared_ptr<SharedPtrTest::Base> one(new SharedPtrTest::Derived());
std::cow_shared_ptr<SharedPtrTest::Base> two(one);
CPPUNIT_ASSERT(!one.unique());
two.get();
CPPUNIT_ASSERT(one.unique());
CPPUNIT_ASSERT(two.unique());
CPPUNIT_ASSERT(one.get() != two.get());
}
......@@ -8,6 +8,7 @@ class SharedPtrTest : public CppUnit::TestFixture
CPPUNIT_TEST_SUITE( SharedPtrTest );
CPPUNIT_TEST( testSharedPtr1 );
CPPUNIT_TEST( testSharedPtr2 );
CPPUNIT_TEST( testSharedPtr3 );
CPPUNIT_TEST_SUITE_END();
 
public:
......@@ -57,12 +58,27 @@ public:
}
};
 
class Base {
public:
virtual Base* clone() const = 0;
};
class Derived : public Base {
public:
virtual Derived* clone() const override {
return new Derived(*this);
}
};
public:
void setUp();
void tearDown();
 
void testSharedPtr1();
void testSharedPtr2();
void testSharedPtr3();
};
 
#endif // TYPE_TRAITS_TEST_H_
......@@ -64,7 +64,6 @@ public:
void setUp();
void tearDown();
 
void testIsBaseOf();
void testVariant();
void testVariantSet();
};
......
#include "VectorTest.h"
#include <vector>
CPPUNIT_TEST_SUITE_NAMED_REGISTRATION( VectorTest, "bits" );
CPPUNIT_TEST_SUITE_REGISTRATION( VectorTest );
void VectorTest::setUp() {
}
void VectorTest::tearDown() {
}
void VectorTest::testVector() {
std::ptr_vector<VectorTest::test> vector;
std::vector<VectorTest::test*> vector2;
for(int i = 0; i < 10; i++) {
VectorTest::test* tmp = new VectorTest::test(i);
vector.push_back(tmp);
vector2.push_back(tmp);
}
int i = 0;
for(VectorTest::test& tmp : vector) {
CPPUNIT_ASSERT(tmp.get() == i);
i++;
}
const decltype(vector)& vector3 = vector;
i = 0;
for(const VectorTest::test& tmp : vector3) {
CPPUNIT_ASSERT(tmp.get() == i);
i++;
}
i = 0;
for(VectorTest::test& tmp : vector3) {
CPPUNIT_ASSERT(tmp.get() == i);
i++;
}
std::ptr_vector<VectorTest::test> vector4;
for(int i = 0; i < 10; i++) {
VectorTest::test* tmp = new VectorTest::test(i+1);
vector4.push_back(tmp);
}
std::compare<std::ptr_vector<VectorTest::test>> comp;
CPPUNIT_ASSERT(comp(vector, vector4) < 0);
}
#ifndef VARIANT_TEST_H_
#define VARIANT_TEST_H_
#include <cppunit/extensions/HelperMacros.h>
#include <compare>
class VectorTest : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( VectorTest );
CPPUNIT_TEST( testVector );
CPPUNIT_TEST_SUITE_END();
public:
struct test {
int i;
test(int i) : i(i) {}
int get() const {
return i;
}
};
public:
void setUp();
void tearDown();
void testVector();
};
namespace std {
template<>
struct compare<VectorTest::test> {
int operator()(const VectorTest::test& first, const VectorTest::test& second) {
return first.get() - second.get();
}
};
} /* namespace std */
#endif // VARIANT_TEST_H_
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment