diff --git a/Makefile b/Makefile index 85af6a4..c306260 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,13 @@ SRCS = main.cpp \ D_HEADERS = ./headers HEADERS = colors.h \ tests.hpp \ + \ enable_if.hpp \ + iterator_traits.hpp \ + reverse_iterator.hpp \ + equal.hpp \ + lexicographical_compare.hpp \ + \ vector.hpp D_TEMPLATES = ./templates diff --git a/headers/equal.hpp b/headers/equal.hpp new file mode 100644 index 0000000..ba7ab74 --- /dev/null +++ b/headers/equal.hpp @@ -0,0 +1,36 @@ + +#ifndef EQUAL_HPP +# define EQUAL_HPP + +namespace ft { + +template < typename InputIt1, typename InputIt2 > + bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2) { + + while (first1 != last1) + { + if (!(*first1 == *first2)) + return false; + ++first1; + ++first2; + } + return true; +} + +template < class InputIt1, class InputIt2, class BinaryPred > + bool equal( InputIt1 first1, InputIt1 last1, InputIt2 first2, BinaryPred pred) { + + while (first1 != last1) + { + if (!pred(*first1, *first2)) + return false; + ++first1; + ++first2; + } + return true; +} + +} // namespace ft + +#endif + diff --git a/headers/iterator_traits.hpp b/headers/iterator_traits.hpp new file mode 100644 index 0000000..e9b3524 --- /dev/null +++ b/headers/iterator_traits.hpp @@ -0,0 +1,44 @@ + +#ifndef ITERATOR_TRAITS_HPP +# define ITERATOR_TRAITS_HPP + +# include // iterator_tag +# include // ptrdiff_t + +namespace ft { + +template < typename Iterator > + struct iterator_traits +{ + typedef typename Iterator::iterator_category iterator_category; + typedef typename Iterator::value_type value_type; + typedef typename Iterator::difference_type difference_type; + typedef typename Iterator::pointer pointer; + typedef typename Iterator::reference reference; +}; + +template < typename T > + struct iterator_traits +{ + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef T* pointer; + typedef T& reference; +}; + +template < typename T > + struct iterator_traits +{ + typedef std::random_access_iterator_tag iterator_category; + typedef T value_type; + typedef std::ptrdiff_t difference_type; + typedef const T* pointer; + typedef const T& reference; +}; + +} // namespace ft + +#endif + +// https://www.fluentcpp.com/2018/05/08/std-iterator-deprecated/ diff --git a/headers/lexicographical_compare.hpp b/headers/lexicographical_compare.hpp new file mode 100644 index 0000000..c1374c0 --- /dev/null +++ b/headers/lexicographical_compare.hpp @@ -0,0 +1,42 @@ + +#ifndef LEXICOGRAPHICAL_COMPARE_HPP +# define LEXICOGRAPHICAL_COMPARE_HPP + +namespace ft { + +template + bool lexicographical_compare + ( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2) { + + while (first1 != last1) + { + if (first2 == last2 || *first2 < *first1) + return false; + else if (*first1 < *first2) + return true; + ++first1; + ++first2; + } + return (first2 != last2); +} + +template + bool lexicographical_compare + ( InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Compare comp) { + + while (first1 != last1) + { + if (first2 == last2 || comp(*first2, *first1)) + return false; + else if (comp(*first1, *first2)) + return true; + ++first1; + ++first2; + } + return (first2 != last2); +} + +} // namespace ft + +#endif + diff --git a/headers/reverse_iterator.hpp b/headers/reverse_iterator.hpp new file mode 100644 index 0000000..db10560 --- /dev/null +++ b/headers/reverse_iterator.hpp @@ -0,0 +1,140 @@ +#ifndef REVERSE_ITERATOR_HPP +# define REVERSE_ITERATOR_HPP + +# include // iterator_tag +# include "iterator_traits.hpp" + +namespace ft { + +template < class Iter > +class reverse_iterator { + +private: + + Iter _it; + typedef ft::iterator_traits _traits; + +public: + typedef Iter iterator_type; + typedef typename _traits::iterator_category iterator_category; + typedef typename _traits::value_type value_type; + typedef typename _traits::difference_type difference_type; + typedef typename _traits::pointer pointer; + typedef typename _traits::reference reference; + + + /**************** + * constructors : + ****************/ + reverse_iterator() + : _it() + {} + explicit reverse_iterator(iterator_type it) + : _it(it) + {} +// reverse_iterator(const reverse_iterator& src) +// : _it(src._it) +// {} + template < class Iterator > + reverse_iterator(const reverse_iterator& rev_it) + : _it(rev_it.base()) + {} + + /********************* + * members functions : + *********************/ +// base -------------------------------------- + iterator_type base() const + { return _it; } +// operator * -------------------------------- + reference operator*() const + { Iter tmp = _it; return *--tmp; } +// operator + -------------------------------- + reverse_iterator operator+(difference_type n) const + { return reverse_iterator(_it - n); } +// operator ++ ------------------------------- + reverse_iterator operator++(int) + { reverse_iterator old(*this); ++(*this); return old; } + reverse_iterator & operator++() + { --_it; return *this; } +// operator += ------------------------------- + reverse_iterator & operator+=(difference_type n) + { _it -= n; return *this; } +// operator - -------------------------------- + reverse_iterator operator-(difference_type n) const + { return reverse_iterator(_it + n); } +// operator -- ------------------------------- + reverse_iterator operator--(int) + { reverse_iterator old(*this); --(*this); return old; } + reverse_iterator & operator--() + { ++_it; return *this; } +// operator -= ------------------------------- + reverse_iterator & operator-=(difference_type n) + { _it += n; return *this; } +// operator -> ------------------------------- + pointer operator->() const + { return &(operator*()); } +// operator [] ------------------------------- + reference operator[] (difference_type n) const + { return _it[-n-1]; } +}; + + /************************* + * non-members functions : + *************************/ +// operator == ------------------------------- +template + bool operator== (const reverse_iterator& lhs, + const reverse_iterator& rhs) + { return lhs.base() == rhs.base(); } +// operator != ------------------------------- +template + bool operator!= (const reverse_iterator& lhs, + const reverse_iterator& rhs) + { return lhs.base() != rhs.base(); } +// operator < -------------------------------- +template + bool operator< (const reverse_iterator& lhs, + const reverse_iterator& rhs) + { return lhs.base() > rhs.base(); } +// operator <= ------------------------------- +template + bool operator<= (const reverse_iterator& lhs, + const reverse_iterator& rhs) + { return lhs.base() >= rhs.base(); } +// operator > -------------------------------- +template + bool operator> (const reverse_iterator& lhs, + const reverse_iterator& rhs) + { return lhs.base() < rhs.base(); } +// operator >= ------------------------------- +template + bool operator>= (const reverse_iterator& lhs, + const reverse_iterator& rhs) + { return lhs.base() <= rhs.base(); } + + + /******************* + * other operators : + *******************/ +// operator + non-member overload ------------ +template + reverse_iterator operator+ + (typename reverse_iterator::difference_type n + ,const reverse_iterator& rhs) + { return reverse_iterator(rhs.base() - n); } + +// operator - non-member overload ------------ +template + typename reverse_iterator::difference_type operator- + (const reverse_iterator& lhs + ,const reverse_iterator& rhs) + { return rhs.base() - lhs.base(); } + + + + +} // namespace ft + +#endif + diff --git a/headers/tests.hpp b/headers/tests.hpp index bb4d54b..f8291bf 100644 --- a/headers/tests.hpp +++ b/headers/tests.hpp @@ -2,18 +2,22 @@ # define TESTS_HPP #include +#include #include "colors.h" #include -#include +#include // std::setw() +#include // std::reverse_iterator +#include // std::make_pair +#include // std::map // ************************* // toogle between test ft and stl -#include #ifdef STL namespace ft = std; #else #include "vector.hpp" + #include "reverse_iterator.hpp" #endif @@ -64,8 +68,8 @@ void tests_vector_constructor(); void tests_vector_operator_assignation(); void tests_vector_begin(); void tests_vector_end(); -//void tests_vector_rbegin(); -//void tests_vector_rend(); +void tests_vector_rbegin(); +void tests_vector_rend(); void tests_vector_size(); void tests_vector_max_size(); void tests_vector_resize(); @@ -84,5 +88,8 @@ void tests_vector_erase(); void tests_vector_swap(); void tests_vector_clear(); void tests_vector_get_allocator(); +void tests_vector_relational_operators(); +void tests_vector_swap_non_member(); +void tests_vector_reverse_iterators(); #endif diff --git a/headers/vector.hpp b/headers/vector.hpp index 5367d3b..78bb779 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -1,16 +1,19 @@ #ifndef VECTOR_HPP # define VECTOR_HPP +# include "colors.h" # include # include # include // std::allocator -# include // std::min +# include // std::min, std::max # include // out_of_range, length_error, logic_error -# include // NULL, size_t, ptrdiff_t +# include // NULL, std::size_t, std::ptrdiff_t -# include "colors.h" # include "enable_if.hpp" # include "is_integral.hpp" +# include "reverse_iterator.hpp" +# include "equal.hpp" +# include "lexicographical_compare.hpp" namespace ft { @@ -28,15 +31,13 @@ public: typedef T * iterator; typedef T const * const_iterator; -// typedef ft::reverse_iterator reverse_iterator; -// typedef ft::reverse_iterator const_reverse_iterator; + typedef ft::reverse_iterator reverse_iterator; + typedef ft::reverse_iterator const_reverse_iterator; // dependent qualified name : // https://en.cppreference.com/w/cpp/keyword/typename typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; -// typedef typename Allocator::pointer pointer; -// typedef typename Allocator::const_pointer const_pointer; @@ -67,11 +68,12 @@ public: iterator end(); const_iterator end() const; // rbegin ------------------------------------ -// reverse_iterator rbegin(); -// const_reverse_iterator rbegin() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; // rend -------------------------------------- -// reverse_iterator rend(); -// const_reverse_iterator rend() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + /************ * capacity : @@ -89,6 +91,7 @@ public: // reserve ----------------------------------- void reserve(size_type n); + /****************** * element access : ******************/ @@ -105,6 +108,7 @@ public: reference back(); const_reference back() const; + /************* * modifiers : *************/ @@ -131,13 +135,13 @@ public: // clear ------------------------------------- void clear(); + /************* * allocator : *************/ // get_allocator ----------------------------- allocator_type get_allocator() const; - private: size_type _size; @@ -150,7 +154,32 @@ private: }; -//std::ostream & operator<<(std::ostream & o, vector const & rhs); + + /************************ + * non-member functions : + ************************/ +// operator == ------------------------------- +template + bool operator== (const vector& lhs, const vector& rhs); +// operator != ------------------------------- +template + bool operator!= (const vector& lhs, const vector& rhs); +// operator < -------------------------------- +template + bool operator< (const vector& lhs, const vector& rhs); +// operator <= ------------------------------- +template + bool operator<= (const vector& lhs, const vector& rhs); +// operator > -------------------------------- +template + bool operator> (const vector& lhs, const vector& rhs); +// operator >= ------------------------------- +template + bool operator>= (const vector& lhs, const vector& rhs); +// swap (vector) ----------------------------- +template + void swap (vector& x, vector& y); + } // namespace ft diff --git a/templates/vector.tpp b/templates/vector.tpp index 3aa3c1a..8f44e93 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -4,6 +4,8 @@ namespace ft { + + /********************************************* * COPLIENS *********************************************/ @@ -39,7 +41,11 @@ VT_TPL template VT:: } // copy constructor -------------------------- VT_TPL VT:: - vector( vector const & src ) { + vector( vector const & src ) + : _size(0) + , _capacity(0) + , _mem_ptr(NULL) + , _allocator(src._allocator) { *this = src; return; @@ -64,13 +70,11 @@ VT_TPL VT & VT:: return *this; } -/********************************************* - * PUBLIC MEMBER FUNCTIONS - *********************************************/ - /************* - * iterators : - *************/ + +/************* + * iterators : + *************/ // begin ------------------------------------- VT_TPL typename VT::iterator VT:: begin() { return _mem_ptr; } @@ -82,19 +86,21 @@ VT_TPL typename VT::iterator VT:: VT_TPL typename VT::const_iterator VT:: end() const { return &_mem_ptr[_size]; } // rbegin ------------------------------------ -//VT_TPL typename VT::reverse_iterator VT:: -// rbegin() { return reverse_iterator(end()); } -//VT_TPL typename VT::const_reverse_iterator VT:: -// rbegin() const { return const_reverse_iterator(end()); } +VT_TPL typename VT::reverse_iterator VT:: + rbegin() { return reverse_iterator(end()); } +VT_TPL typename VT::const_reverse_iterator VT:: + rbegin() const { return const_reverse_iterator(end()); } // rend -------------------------------------- -//VT_TPL typename VT::reverse_iterator VT:: -// rend() { return reverse_iterator(begin()); } -//VT_TPL typename VT::const_reverse_iterator VT:: -// rend() const { return const_reverse_iterator(begin()); } +VT_TPL typename VT::reverse_iterator VT:: + rend() { return reverse_iterator(begin()); } +VT_TPL typename VT::const_reverse_iterator VT:: + rend() const { return const_reverse_iterator(begin()); } - /************ - * capacity : - ************/ + + +/************ + * capacity : + ************/ // size -------------------------------------- VT_TPL typename VT::size_type VT:: size( ) const { return _size; } @@ -153,9 +159,11 @@ VT_TPL void VT:: _mem_ptr = tmp_ptr; } - /****************** - * element access : - ******************/ + + +/****************** + * element access : + ******************/ // operator[] -------------------------------- VT_TPL typename VT::reference VT:: operator[](size_type n) { return _mem_ptr[n]; } @@ -187,9 +195,11 @@ VT_TPL typename VT::reference VT:: VT_TPL typename VT::const_reference VT:: back() const { return (_mem_ptr[_size - 1]); } - /************* - * modifiers : - *************/ + + +/************* + * modifiers : + *************/ // assign ------------------------------------ VT_TPL template typename enable_if< !is_integral::value,void >::type VT:: @@ -338,9 +348,6 @@ typename enable_if< !is_integral::value,void >::type VT:: _destroy(position, std::min(position + n, it_end)); } -// for (size_type i = 0; i < n; i++, position++) -// _allocator.construct(position, val); - while (first != last) { _allocator.construct(position, *first); @@ -421,10 +428,10 @@ VT_TPL typename VT::allocator_type VT:: get_allocator() const { return (_allocator); } + /********************************************* * PRIVATE MEMBER FUNCTIONS *********************************************/ - VT_TPL void VT:: _destroy(iterator first, iterator last) { @@ -434,7 +441,6 @@ VT_TPL void VT:: first++; } } - VT_TPL void VT:: _increment_capacity(size_type n) { @@ -445,30 +451,54 @@ VT_TPL void VT:: } -/********************************************* - * OPERATORS - *********************************************/ - -//std::ostream & operator<<(std::ostream & o, vector const & rhs) -//{ -// o << rhs.getFoo(); -// return (o); -//} - /********************************************* * NESTED CLASS *********************************************/ - //void vector::Class::function() {} + /********************************************* * STATICS *********************************************/ - //std::string const vector::_bar = "bar"; + + +/************************ + * non-member functions : + ************************/ +// operator == ------------------------------- +VT_TPL + bool operator== (const VT & lhs, const VT & rhs) { + + if (lhs.size() != rhs.size()) + return false; + return ft::equal(lhs.begin(), lhs.end(), rhs.begin()); +} +// operator < -------------------------------- +VT_TPL + bool operator< (const VT & lhs, const VT & rhs) { + + return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} +// operator != ------------------------------- +VT_TPL + bool operator!= (const VT & lhs, const VT & rhs) { return !(lhs == rhs); } +// operator <= ------------------------------- +VT_TPL + bool operator<= (const VT & lhs, const VT & rhs) { return !(lhs > rhs); } +// operator > -------------------------------- +VT_TPL + bool operator> (const VT & lhs, const VT & rhs) { return (rhs < lhs); } +// operator >= ------------------------------- +VT_TPL + bool operator>= (const VT & lhs, const VT & rhs) { return !(lhs < rhs); } +// swap (vector) ------------------------------- +VT_TPL + void swap (VT & lhs, VT & rhs) { lhs.swap(rhs); } + } // namespace ft #undef VT diff --git a/tests/main.cpp b/tests/main.cpp index 7a112ca..074d8df 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -18,12 +18,12 @@ std::string test_title; int main() { // VECTOR -// tests_vector_constructor(); + tests_vector_constructor(); tests_vector_operator_assignation(); tests_vector_begin(); tests_vector_end(); -// tests_vector_rbegin(); -// tests_vector_rend(); + tests_vector_rbegin(); + tests_vector_rend(); tests_vector_size(); tests_vector_max_size(); tests_vector_resize(); @@ -42,6 +42,9 @@ int main() { tests_vector_swap(); tests_vector_clear(); tests_vector_get_allocator(); + tests_vector_relational_operators(); + tests_vector_swap_non_member(); + tests_vector_reverse_iterators(); // MAP // tests_map_constructor(); diff --git a/tests/test.sh b/tests/test.sh index edbbfec..dbdca9a 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -1,12 +1,18 @@ #!/bin/bash # cd $(dirname $0) +TEST_DIR=$(dirname $0) +OUTPUT_STL="output_stl.log" +OUTPUT_FT="output_ft.log" + make stl > /dev/null echo -e "\nstl :" -time ./containers > tests/output_stl.log +time ./containers > tests/$OUTPUT_STL make ft > /dev/null echo -e "\nft :" -time ./containers > tests/output_ft.log +time ./containers > tests/$OUTPUT_FT -diff --context=0 --color=always tests/output_stl.log tests/output_ft.log +diff --context=0 --color=always tests/$OUTPUT_STL tests/$OUTPUT_FT + +/bin/rm $TEST_DIR/$OUTPUT_STL $TEST_DIR/$OUTPUT_FT diff --git a/tests/tests_vectors.cpp b/tests/tests_vectors.cpp index 6fb561f..89d4c99 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vectors.cpp @@ -1,11 +1,7 @@ #ifndef TESTS_VECTORS_CPP #define TESTS_VECTORS_CPP -#include -#include -//#include "colors.h" #include "tests.hpp" -#include // std::setw() void tests_vector_constructor() @@ -106,7 +102,6 @@ void tests_vector_end() TESTEND } -/* void tests_vector_rbegin() { TEST(vector::rbegin) @@ -152,8 +147,6 @@ void tests_vector_rend() } TESTEND } -*/ - void tests_vector_size() { @@ -967,4 +960,181 @@ void tests_vector_get_allocator() TESTEND } +void tests_vector_relational_operators() +{ + TEST(ft::relational operators) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector foo (3,100); // three ints with a value of 100 + ft::vector bar (2,200); // two ints with a value of 200 + + if (foo==bar) std::cout << "foo and bar are equal\n"; + if (foo!=bar) std::cout << "foo and bar are not equal\n"; + if (foo< bar) std::cout << "foo is less than bar\n"; + if (foo> bar) std::cout << "foo is greater than bar\n"; + if (foo<=bar) std::cout << "foo is less than or equal to bar\n"; + if (foo>=bar) std::cout << "foo is greater than or equal to bar\n"; + } + TESTEND +} +void tests_vector_swap_non_member() +{ + TEST(ft::swap vector) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector foo (3,100); // three ints with a value of 100 + ft::vector bar (5,200); // five ints with a value of 200 + + foo.swap(bar); + + std::cout << "foo contains:"; + for (ft::vector::iterator it = foo.begin(); it!=foo.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + + std::cout << "bar contains:"; + for (ft::vector::iterator it = bar.begin(); it!=bar.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + TESTEND +} + +void tests_vector_reverse_iterators() +{ + TEST(ft::reverse_iterator) + { + // title + TITLE(cplusplus.com reference) + TITLE(::constructor ::operator* ::operator++(int)) + + ft::vector myvector; + for (int i=0; i<10; i++) myvector.push_back(i); + typedef ft::vector::iterator iter_type; + // ? 0 1 2 3 4 5 6 7 8 9 ? + iter_type from (myvector.begin()); // ^ + iter_type until (myvector.end()); // ^ + ft::reverse_iterator rev_until (from); // ^ + ft::reverse_iterator rev_from (until); // ^ + + std::cout << "myvector:"; + while (rev_from != rev_until) + std::cout << ' ' << *rev_from++; + std::cout << '\n'; + + + // title + TITLE(::operator++) + + std::cout << "myvector:"; + while (rev_from != rev_until) { + std::cout << ' ' << *rev_from; + ++rev_from; + } + std::cout << '\n'; + + + // title + TITLE(::base) + + ft::reverse_iterator rev_end (myvector.begin()); + ft::reverse_iterator rev_begin (myvector.end()); + std::cout << "myvector:"; + for (iter_type it = rev_end.base(); it != rev_begin.base(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + + + // title + TITLE(::operator+) + + ft::reverse_iterator rev_it_add; + rev_it_add = myvector.rbegin() +3; + std::cout << "The fourth element from the end is: " << *rev_it_add << '\n'; + + + // title + TITLE(::operator+=) + + ft::reverse_iterator rev_it_add_equal = myvector.rbegin(); + rev_it_add_equal += 2; + std::cout << "The third element from the end is: " << *rev_it_add_equal << '\n'; + + + // title + TITLE(::operator-) + + ft::reverse_iterator rev_it_minus; + rev_it_minus = myvector.rend() - 3; + std::cout << "myvector.rend()-3 points to: " << *rev_it_minus << '\n'; + + + // title + TITLE(::operator--) + + ft::reverse_iterator rev_it_minus_minus = rev_begin; + while ( rev_it_minus_minus != rev_end ) + std::cout << *rev_it_minus_minus++ << ' '; + std::cout << '\n'; + + while ( rev_it_minus_minus != rev_begin ) + std::cout << *(--rev_it_minus_minus) << ' '; + std::cout << '\n'; + + + // title + TITLE(::operator-=) + + ft::reverse_iterator rev_it_minus_equal = myvector.rend(); + rev_it_minus_equal -= 4; + std::cout << "rev_it_minus_equal now points to: " << *rev_it_minus_equal << '\n'; + + + // title + TITLE(::operator->) + + std::map numbers; + numbers.insert (std::make_pair(1,"one")); + numbers.insert (std::make_pair(2,"two")); + numbers.insert (std::make_pair(3,"three")); + + typedef std::map::iterator map_iter; + ft::reverse_iterator rev_map_end (numbers.begin()); + ft::reverse_iterator rev_map_ite (numbers.end()); + + for ( ; rev_map_ite != rev_map_end ; ++rev_map_ite ) + std::cout << rev_map_ite->first << ' ' << rev_map_ite->second << '\n'; + + + // title + TITLE(::operator[]) + + ft::reverse_iterator rev_it_at = myvector.rbegin(); + std::cout << "The fourth element from the end is: " << rev_it_at[3] << '\n'; + + + // title + TITLE(::operator- non-member) + + ft::reverse_iterator::iterator> rev_it_from,rev_it_until; + rev_it_from = myvector.rbegin(); + rev_it_until = myvector.rend(); + std::cout << "myvector has " << (rev_it_until-rev_it_from) << " elements.\n"; + + + // title + TITLE(::operator+ non-member) + + ft::reverse_iterator rev_it_n_memb; + rev_it_n_memb = 3 + myvector.rbegin(); + std::cout << "The fourth element from the end is: " << *rev_it_n_memb << '\n'; + + } + TESTEND +} + #endif