From 1a8b81c3cfe33d269ed0ea003bb2ee0c5df0ada9 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 31 May 2022 15:49:14 +0200 Subject: [PATCH 01/53] added standard test from cplusplus --- Makefile | 68 +++++++ headers/colors.h | 25 +++ main.cpp | 455 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 548 insertions(+) create mode 100644 Makefile create mode 100644 headers/colors.h diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..dfceebd --- /dev/null +++ b/Makefile @@ -0,0 +1,68 @@ +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # +# . name = value \ . += append to a variable # +# VARIABLES . value . != set result of command # +# . name is case sensitive . ?= set if not already set # +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # + +NAME = containers + +CC = c++ +EXT = cpp + +CFLAGS = -Wall -Wextra -Werror $(INCLUDES) +CFLAGS += -std=c++98 + +VPATH = $(D_SRCS) + +LIBS = + +INCLUDES = -I$(D_HEADERS) + +D_SRCS = srcs +SRCS = main.cpp + +D_HEADERS = headers +HEADERS = colors.h + +D_OBJS = builds +OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) + +ifeq "$(D_OBJS)" "." + RM_OBJS = rm -f $(OBJS) +else + RM_OBJS = rm -rf $(D_OBJS) +endif + + +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # +# . target: prerequisites . $@ : target # +# RULES . recipe . $< : 1st prerequisite # +# . recipe . $^ : all prerequisites # +# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # + +all: $(NAME) + +$(D_OBJS)/%.o: %.$(EXT) | $(D_OBJS) + $(CC) $(CFLAGS) -c $< -o $@ + +$(D_OBJS): + mkdir $@ + +$(OBJS): $(HEADERS:%=$(D_HEADERS)/%) + +$(NAME): $(OBJS) + $(CC) $(OBJS) -o $@ $(LIBS) + +leaks: $(NAME) + valgrind --leak-check=full --show-leak-kinds=all ./$(NAME) + +clean: + $(RM_OBJS) + +fclean: clean + rm -f $(NAME) + +re: fclean all + +.PHONY : all clean fclean re + diff --git a/headers/colors.h b/headers/colors.h new file mode 100644 index 0000000..0374e42 --- /dev/null +++ b/headers/colors.h @@ -0,0 +1,25 @@ +#ifndef COLORS_H +# define COLORS_H + +# define GRAY "\e[0;30m" +# define RED "\e[0;31m" +# define GREEN "\e[0;32m" +# define YELLOW "\e[0;33m" +# define BLUE "\e[0;34m" +# define PURPLE "\e[0;35m" +# define CYAN "\e[0;36m" +# define WHITE "\e[0;37m" + +# define B_GRAY "\e[1;30m" +# define B_RED "\e[1;31m" +# define B_GREEN "\e[1;32m" +# define B_YELLOW "\e[1;33m" +# define B_BLUE "\e[1;34m" +# define B_PURPLE "\e[1;35m" +# define B_CYAN "\e[1;36m" +# define B_WHITE "\e[1;37m" + +# define RESET "\e[0m" + +#endif + diff --git a/main.cpp b/main.cpp index e1329eb..296bf4a 100644 --- a/main.cpp +++ b/main.cpp @@ -1,3 +1,456 @@ +#include +#include +#include "colors.h" +#include + +#define N_TEST "1" + +int main() { + int i = 0; + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::vector (constructor) :" RESET "\n"; + { + // constructors used in the same order as described above: + std::vector first; // empty vector of ints + std::vector second (4,100); // four ints with value 100 + std::vector third (second.begin(),second.end()); // iterating through second + std::vector fourth (third); // a copy of third + + // the iterator constructor can also be used to construct from arrays: + int myints[] = {16,2,77,29}; + std::vector fifth (myints, myints + sizeof(myints) / sizeof(int) ); + + std::cout << "The contents of fifth are:"; + for (std::vector::iterator it = fifth.begin(); it != fifth.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::=operator :" RESET "\n"; + { + std::vector foo (3,0); + std::vector bar (5,0); + + bar = foo; + foo = std::vector(); + + std::cout << "Size of foo: " << int(foo.size()) << '\n'; + std::cout << "Size of bar: " << int(bar.size()) << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::begin :" RESET "\n"; + { + std::vector myvector; + for (int i=1; i<=5; i++) myvector.push_back(i); + + std::cout << "myvector contains:"; + for (std::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::end :" RESET "\n"; + { + std::vector myvector; + for (int i=1; i<=5; i++) myvector.push_back(i); + + std::cout << "myvector contains:"; + for (std::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::rbegin :" RESET "\n"; + { + std::vector myvector (5); // 5 default-constructed ints + + int i=0; + + std::vector::reverse_iterator rit = myvector.rbegin(); + for (; rit!= myvector.rend(); ++rit) + *rit = ++i; + + std::cout << "myvector contains:"; + for (std::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::rend :" RESET "\n"; + { + std::vector myvector (5); // 5 default-constructed ints + + std::vector::reverse_iterator rit = myvector.rbegin(); + + int i=0; + for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit) + *rit = ++i; + + std::cout << "myvector contains:"; + for (std::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::size :" RESET "\n"; + { + std::vector myints; + std::cout << "0. size: " << myints.size() << '\n'; + + for (int i=0; i<10; i++) myints.push_back(i); + std::cout << "1. size: " << myints.size() << '\n'; + + myints.insert (myints.end(),10,100); + std::cout << "2. size: " << myints.size() << '\n'; + + myints.pop_back(); + std::cout << "3. size: " << myints.size() << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::max_size :" RESET "\n"; + { + std::vector myvector; + + // set some content in the vector: + for (int i=0; i<100; i++) myvector.push_back(i); + + std::cout << "size: " << myvector.size() << "\n"; + std::cout << "capacity: " << myvector.capacity() << "\n"; + std::cout << "max_size: " << myvector.max_size() << "\n"; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::resize :" RESET "\n"; + { + std::vector myvector; + + // set some initial content: + for (int i = 1; i < 10; i++) myvector.push_back(i); + + myvector.resize(5); + myvector.resize(8,100); + myvector.resize(12); + + std::cout << "myvector contains:"; + for (unsigned int i = 0; i < myvector.size(); i++) + std::cout << ' ' << myvector[i]; + std::cout << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::capacity :" RESET "\n"; + { + std::vector myvector; + + // set some content in the vector: + for (int i=0; i<100; i++) myvector.push_back(i); + + std::cout << "size: " << (int) myvector.size() << '\n'; + std::cout << "capacity: " << (int) myvector.capacity() << '\n'; + std::cout << "max_size: " << (int) myvector.max_size() << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::empty :" RESET "\n"; + { + std::vector myvector; + int sum (0); + + for (int i=1;i<=10;i++) myvector.push_back(i); + + while (!myvector.empty()) + { + sum += myvector.back(); + myvector.pop_back(); + } + + std::cout << "total: " << sum << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::reserve :" RESET "\n"; + { + std::vector::size_type sz; + + std::vector foo; + sz = foo.capacity(); + std::cout << "making foo grow:\n"; + for (int i=0; i<100; ++i) { + foo.push_back(i); + if (sz!=foo.capacity()) { + sz = foo.capacity(); + std::cout << "capacity changed: " << sz << '\n'; + } + } + + std::vector bar; + sz = bar.capacity(); + bar.reserve(100); // this is the only difference with foo above + std::cout << "making bar grow:\n"; + for (int i=0; i<100; ++i) { + bar.push_back(i); + if (sz!=bar.capacity()) { + sz = bar.capacity(); + std::cout << "capacity changed: " << sz << '\n'; + } + } + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::operator[] :" RESET "\n"; + { + std::vector myvector (10); // 10 zero-initialized elements + + std::vector::size_type sz = myvector.size(); + + // assign some values: + for (unsigned i=0; i myvector (10); // 10 zero-initialized ints + + // assign some values: + for (unsigned i=0; i myvector; + + myvector.push_back(78); + myvector.push_back(16); + + // now front equals 78, and back 16 + + myvector.front() -= myvector.back(); + + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::back :" RESET "\n"; + { + std::vector myvector; + + myvector.push_back(78); + myvector.push_back(16); + + // now front equals 78, and back 16 + + myvector.front() -= myvector.back(); + + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::assign :" RESET "\n"; + { + std::vector first; + std::vector second; + std::vector third; + + first.assign (7,100); // 7 ints with a value of 100 + + std::vector::iterator it; + it=first.begin()+1; + + second.assign (it,first.end()-1); // the 5 central values of first + + int myints[] = {1776,7,4}; + third.assign (myints,myints+3); // assigning from array. + + std::cout << "Size of first: " << int (first.size()) << '\n'; + std::cout << "Size of second: " << int (second.size()) << '\n'; + std::cout << "Size of third: " << int (third.size()) << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::push_back :" RESET "\n"; + { + std::vector myvector; + + /* original : + int myint; + std::cout << "Please enter some integers (enter 0 to end):\n"; + do { + std::cin >> myint; + myvector.push_back (myint); + } while (myint); + */ + // replaced by : + int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; + int size = sizeof(myint) / sizeof(myint[0]); + for (int i = 0; i < size; i++) + myvector.push_back (myint[i]); + + std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n"; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::pop_back :" RESET "\n"; + { + std::vector myvector; + int sum (0); + myvector.push_back (100); + myvector.push_back (200); + myvector.push_back (300); + + while (!myvector.empty()) + { + sum+=myvector.back(); + myvector.pop_back(); + } + + std::cout << "The elements of myvector add up to " << sum << '\n'; + } + + std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " + << "vector::insert :" RESET "\n"; + { + std::vector myvector (3,100); + std::vector::iterator it; + + it = myvector.begin(); + it = myvector.insert ( it , 200 ); + + myvector.insert (it,2,300); + + // "it" no longer valid, get a new one: + it = myvector.begin(); + + std::vector anothervector (2,400); + myvector.insert (it+2,anothervector.begin(),anothervector.end()); + + int myarray [] = { 501,502,503 }; + myvector.insert (myvector.begin(), myarray, myarray+3); + + std::cout << "myvector contains:"; + for (it=myvector.begin(); it myvector; + + // set some values (from 1 to 10) + for (int i=1; i<=10; i++) myvector.push_back(i); + + // erase the 6th element + myvector.erase (myvector.begin()+5); + + // erase the first 3 elements: + myvector.erase (myvector.begin(),myvector.begin()+3); + + std::cout << "myvector contains:"; + for (unsigned i=0; i foo (3,100); // three ints with a value of 100 + std::vector bar (5,200); // five ints with a value of 200 + + foo.swap(bar); + + std::cout << "foo contains:"; + for (unsigned i=0; i myvector; + myvector.push_back (100); + myvector.push_back (200); + myvector.push_back (300); + + std::cout << "myvector contains:"; + for (unsigned i=0; i myvector; + int * p; + unsigned int i; + + // allocate an array with space for 5 elements using vector's allocator: + p = myvector.get_allocator().allocate(5); + + // construct values in-place on the array: + for (i=0; i<5; i++) myvector.get_allocator().construct(&p[i],i); + + std::cout << "The allocated array contains:"; + for (i=0; i<5; i++) std::cout << ' ' << p[i]; + std::cout << '\n'; + + // destroy and deallocate: + for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]); + myvector.get_allocator().deallocate(p,5); + } + + return 0; +} + +/* original main + #include #include #include @@ -114,3 +567,5 @@ int main(int argc, char** argv) { std::cout << std::endl; return (0); } + +*/ From 5e65691bc8a2de02e8fcb5af35b935228712907d Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 31 May 2022 19:28:22 +0200 Subject: [PATCH 02/53] test structure is functionnal --- main.cpp | 139 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 81 insertions(+), 58 deletions(-) diff --git a/main.cpp b/main.cpp index 296bf4a..6a1714f 100644 --- a/main.cpp +++ b/main.cpp @@ -3,13 +3,57 @@ #include "colors.h" #include -#define N_TEST "1" +/* +#define N_TEST "24" +#define TEST(s) std::cout \ + << "\n" B_YELLOW "[" << ++test << "/" N_TEST "] " \ + << #s " :" RESET "\n"; +*/ + +#define TEST \ + {\ + struct tester : public testt {\ + void func() +#define TESTNAME(s) \ + };\ + test = new(tester);\ + test->title = #s;\ + testouille.push_back(test);\ + } + +struct testt { + std::string title; + virtual void func() { + std::cout << "houre\n"; + } +}; int main() { - int i = 0; - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::vector (constructor) :" RESET "\n"; + std::vector testouille; + testt *test; + + TEST { + std::cout << "here\n"; + } TESTNAME(name of first test) + + TEST { + std::cout << "here2\n"; + } TESTNAME(name of second test) + + int size = testouille.size(); + for(int i = 0; i < size; i++) + { + std::cout + << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] " \ + << testouille[i]->title << " :" RESET "\n"; + testouille[i]->func(); + } + +/* + int test = 0; + + TEST(vector::vector (constructor)) { // constructors used in the same order as described above: std::vector first; // empty vector of ints @@ -27,8 +71,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::=operator :" RESET "\n"; + TEST(vector::=operator) { std::vector foo (3,0); std::vector bar (5,0); @@ -40,8 +83,7 @@ int main() { std::cout << "Size of bar: " << int(bar.size()) << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::begin :" RESET "\n"; + TEST(vector::begin) { std::vector myvector; for (int i=1; i<=5; i++) myvector.push_back(i); @@ -52,8 +94,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::end :" RESET "\n"; + TEST(vector::end) { std::vector myvector; for (int i=1; i<=5; i++) myvector.push_back(i); @@ -64,8 +105,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::rbegin :" RESET "\n"; + TEST(vector::rbegin) { std::vector myvector (5); // 5 default-constructed ints @@ -81,8 +121,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::rend :" RESET "\n"; + TEST(vector::rend) { std::vector myvector (5); // 5 default-constructed ints @@ -98,8 +137,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::size :" RESET "\n"; + TEST(vector::size) { std::vector myints; std::cout << "0. size: " << myints.size() << '\n'; @@ -114,8 +152,7 @@ int main() { std::cout << "3. size: " << myints.size() << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::max_size :" RESET "\n"; + TEST(vector::max_size) { std::vector myvector; @@ -127,8 +164,7 @@ int main() { std::cout << "max_size: " << myvector.max_size() << "\n"; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::resize :" RESET "\n"; + TEST(vector::resize) { std::vector myvector; @@ -145,8 +181,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::capacity :" RESET "\n"; + TEST(vector::capacity) { std::vector myvector; @@ -158,8 +193,7 @@ int main() { std::cout << "max_size: " << (int) myvector.max_size() << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::empty :" RESET "\n"; + TEST(vector::empty) { std::vector myvector; int sum (0); @@ -175,8 +209,7 @@ int main() { std::cout << "total: " << sum << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::reserve :" RESET "\n"; + TEST(vector::reserve) { std::vector::size_type sz; @@ -204,8 +237,7 @@ int main() { } } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::operator[] :" RESET "\n"; + TEST(vector::operator[]) { std::vector myvector (10); // 10 zero-initialized elements @@ -229,8 +261,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::at :" RESET "\n"; + TEST(vector::at) { std::vector myvector (10); // 10 zero-initialized ints @@ -244,8 +275,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::front :" RESET "\n"; + TEST(vector::front) { std::vector myvector; @@ -259,8 +289,7 @@ int main() { std::cout << "myvector.front() is now " << myvector.front() << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::back :" RESET "\n"; + TEST(vector::back) { std::vector myvector; @@ -274,8 +303,7 @@ int main() { std::cout << "myvector.front() is now " << myvector.front() << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::assign :" RESET "\n"; + TEST(vector::assign) { std::vector first; std::vector second; @@ -296,19 +324,19 @@ int main() { std::cout << "Size of third: " << int (third.size()) << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::push_back :" RESET "\n"; + TEST(vector::push_back) { std::vector myvector; - /* original : - int myint; - std::cout << "Please enter some integers (enter 0 to end):\n"; - do { - std::cin >> myint; - myvector.push_back (myint); - } while (myint); - */ + // original : + // + // int myint; + // std::cout << "Please enter some integers (enter 0 to end):\n"; + // do { + // std::cin >> myint; + // myvector.push_back (myint); + // } while (myint); + // // replaced by : int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; int size = sizeof(myint) / sizeof(myint[0]); @@ -318,8 +346,7 @@ int main() { std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n"; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::pop_back :" RESET "\n"; + TEST(vector::pop_back) { std::vector myvector; int sum (0); @@ -336,8 +363,7 @@ int main() { std::cout << "The elements of myvector add up to " << sum << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::insert :" RESET "\n"; + TEST(vector::insert) { std::vector myvector (3,100); std::vector::iterator it; @@ -362,8 +388,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::erase :" RESET "\n"; + TEST(vector::erase) { std::vector myvector; @@ -382,8 +407,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::swap :" RESET "\n"; + TEST(vector::swap) { std::vector foo (3,100); // three ints with a value of 100 std::vector bar (5,200); // five ints with a value of 200 @@ -401,8 +425,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::clear :" RESET "\n"; + TEST(vector::clear) { std::vector myvector; myvector.push_back (100); @@ -424,8 +447,7 @@ int main() { std::cout << '\n'; } - std::cout << B_YELLOW "\n[" << ++i << "/" N_TEST "] " - << "vector::get_allocator :" RESET "\n"; + TEST(vector::get_allocator) { std::vector myvector; int * p; @@ -445,6 +467,7 @@ int main() { for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]); myvector.get_allocator().deallocate(p,5); } +*/ return 0; } From 0e51cc655c28ed3bd20b41afc30e6027120bc98a Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 31 May 2022 19:52:03 +0200 Subject: [PATCH 03/53] creation of tests.h --- Makefile | 3 +- headers/colors.h | 1 - headers/tests.h | 28 +++++ main.cpp | 318 ++++++++++++++++++++++++----------------------- 4 files changed, 190 insertions(+), 160 deletions(-) create mode 100644 headers/tests.h diff --git a/Makefile b/Makefile index dfceebd..4a2a272 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,8 @@ D_SRCS = srcs SRCS = main.cpp D_HEADERS = headers -HEADERS = colors.h +HEADERS = colors.h \ + tests.h D_OBJS = builds OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) diff --git a/headers/colors.h b/headers/colors.h index 0374e42..05d4f2c 100644 --- a/headers/colors.h +++ b/headers/colors.h @@ -22,4 +22,3 @@ # define RESET "\e[0m" #endif - diff --git a/headers/tests.h b/headers/tests.h new file mode 100644 index 0000000..12a747e --- /dev/null +++ b/headers/tests.h @@ -0,0 +1,28 @@ +#ifndef TESTS_H +# define TESTS_H + +#include + +# define TEST(s) \ + {\ + test_title = #s;\ + struct tester : public test_base {\ + void func() + +# define TESTEND \ + };\ + test = new(tester);\ + test->title = test_title;\ + test_list.push_back(test);\ + } + +struct test_base { + std::string title; + virtual void func() {} +}; + +std::vector test_list; +test_base *test; +std::string test_title; + +#endif diff --git a/main.cpp b/main.cpp index 6a1714f..656e66a 100644 --- a/main.cpp +++ b/main.cpp @@ -1,58 +1,12 @@ #include #include #include "colors.h" +#include "tests.h" + #include -/* -#define N_TEST "24" -#define TEST(s) std::cout \ - << "\n" B_YELLOW "[" << ++test << "/" N_TEST "] " \ - << #s " :" RESET "\n"; -*/ - -#define TEST \ - {\ - struct tester : public testt {\ - void func() -#define TESTNAME(s) \ - };\ - test = new(tester);\ - test->title = #s;\ - testouille.push_back(test);\ - } - -struct testt { - std::string title; - virtual void func() { - std::cout << "houre\n"; - } -}; - int main() { - std::vector testouille; - testt *test; - - TEST { - std::cout << "here\n"; - } TESTNAME(name of first test) - - TEST { - std::cout << "here2\n"; - } TESTNAME(name of second test) - - int size = testouille.size(); - for(int i = 0; i < size; i++) - { - std::cout - << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] " \ - << testouille[i]->title << " :" RESET "\n"; - testouille[i]->func(); - } - -/* - int test = 0; - TEST(vector::vector (constructor)) { // constructors used in the same order as described above: @@ -70,6 +24,7 @@ int main() { std::cout << ' ' << *it; std::cout << '\n'; } + TESTEND TEST(vector::=operator) { @@ -82,6 +37,7 @@ int main() { std::cout << "Size of foo: " << int(foo.size()) << '\n'; std::cout << "Size of bar: " << int(bar.size()) << '\n'; } + TESTEND TEST(vector::begin) { @@ -93,6 +49,7 @@ int main() { std::cout << ' ' << *it; std::cout << '\n'; } + TESTEND TEST(vector::end) { @@ -104,6 +61,7 @@ int main() { std::cout << ' ' << *it; std::cout << '\n'; } + TESTEND TEST(vector::rbegin) { @@ -120,6 +78,7 @@ int main() { std::cout << ' ' << *it; std::cout << '\n'; } + TESTEND TEST(vector::rend) { @@ -136,6 +95,7 @@ int main() { std::cout << ' ' << *it; std::cout << '\n'; } + TESTEND TEST(vector::size) { @@ -151,6 +111,7 @@ int main() { myints.pop_back(); std::cout << "3. size: " << myints.size() << '\n'; } + TESTEND TEST(vector::max_size) { @@ -163,6 +124,7 @@ int main() { std::cout << "capacity: " << myvector.capacity() << "\n"; std::cout << "max_size: " << myvector.max_size() << "\n"; } + TESTEND TEST(vector::resize) { @@ -180,6 +142,7 @@ int main() { std::cout << ' ' << myvector[i]; std::cout << '\n'; } + TESTEND TEST(vector::capacity) { @@ -192,6 +155,7 @@ int main() { std::cout << "capacity: " << (int) myvector.capacity() << '\n'; std::cout << "max_size: " << (int) myvector.max_size() << '\n'; } + TESTEND TEST(vector::empty) { @@ -208,6 +172,7 @@ int main() { std::cout << "total: " << sum << '\n'; } + TESTEND TEST(vector::reserve) { @@ -236,6 +201,7 @@ int main() { } } } + TESTEND TEST(vector::operator[]) { @@ -260,6 +226,7 @@ int main() { std::cout << ' ' << myvector[i]; std::cout << '\n'; } + TESTEND TEST(vector::at) { @@ -274,6 +241,7 @@ int main() { std::cout << ' ' << myvector.at(i); std::cout << '\n'; } + TESTEND TEST(vector::front) { @@ -288,6 +256,7 @@ int main() { std::cout << "myvector.front() is now " << myvector.front() << '\n'; } + TESTEND TEST(vector::back) { @@ -302,6 +271,7 @@ int main() { std::cout << "myvector.front() is now " << myvector.front() << '\n'; } + TESTEND TEST(vector::assign) { @@ -323,6 +293,7 @@ int main() { std::cout << "Size of second: " << int (second.size()) << '\n'; std::cout << "Size of third: " << int (third.size()) << '\n'; } + TESTEND TEST(vector::push_back) { @@ -345,6 +316,7 @@ int main() { std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n"; } + TESTEND TEST(vector::pop_back) { @@ -362,6 +334,7 @@ int main() { std::cout << "The elements of myvector add up to " << sum << '\n'; } + TESTEND TEST(vector::insert) { @@ -387,6 +360,7 @@ int main() { std::cout << ' ' << *it; std::cout << '\n'; } + TESTEND TEST(vector::erase) { @@ -406,6 +380,7 @@ int main() { std::cout << ' ' << myvector[i]; std::cout << '\n'; } + TESTEND TEST(vector::swap) { @@ -424,6 +399,7 @@ int main() { std::cout << ' ' << bar[i]; std::cout << '\n'; } + TESTEND TEST(vector::clear) { @@ -446,6 +422,7 @@ int main() { std::cout << ' ' << myvector[i]; std::cout << '\n'; } + TESTEND TEST(vector::get_allocator) { @@ -467,128 +444,153 @@ int main() { for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]); myvector.get_allocator().deallocate(p,5); } -*/ + TESTEND + + + // execute tests and print them : + + int size = test_list.size(); + for(int i = 0; i < size; i++) + { + std::cout + << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] " + << test_list[i]->title << " :" RESET "\n"; + test_list[i]->func(); + } return 0; } -/* original main - -#include -#include -#include -#if 1 //CREATE A REAL STL EXAMPLE - #include - #include - #include - namespace ft = std; -#else - #include - #include - #include -#endif - -#include - -#define MAX_RAM 4294967296 -#define BUFFER_SIZE 4096 -struct Buffer -{ - int idx; - char buff[BUFFER_SIZE]; -}; -#define COUNT (MAX_RAM / (int)sizeof(Buffer)) -template -class MutantStack : public ft::stack -{ -public: - MutantStack() {} - MutantStack(const MutantStack& src) { *this = src; } - MutantStack& operator=(const MutantStack& rhs) - { - this->c = rhs.c; - return *this; - } - ~MutantStack() {} - typedef typename ft::stack::container_type::iterator iterator; - iterator begin() { return this->c.begin(); } - iterator end() { return this->c.end(); } -}; -int main(int argc, char** argv) { - if (argc != 2) - { - std::cerr << "Usage: ./test seed" << std::endl; - std::cerr << "Provide a seed please" << std::endl; - std::cerr << "Count value:" << COUNT << std::endl; - return 1; - } - const int seed = atoi(argv[1]); - srand(seed); - ft::vector vector_str; - ft::vector vector_int; - ft::stack stack_int; - ft::vector vector_buffer; - ft::stack > stack_deq_buffer; - ft::map map_int; - for (int i = 0; i < COUNT; i++) - { - vector_buffer.push_back(Buffer()); - } - for (int i = 0; i < COUNT; i++) - { - const int idx = rand() % COUNT; - vector_buffer[idx].idx = 5; - } - ft::vector().swap(vector_buffer); - try - { - for (int i = 0; i < COUNT; i++) - { - const int idx = rand() % COUNT; - vector_buffer.at(idx); - std::cerr << "Error: THIS VECTOR SHOULD BE EMPTY!!" < copy = map_int; - } - MutantStack iterable_stack; - for (char letter = 'a'; letter <= 'z'; letter++) - iterable_stack.push(letter); - for (MutantStack::iterator it = iterable_stack.begin(); it != iterable_stack.end(); it++) - { - std::cout << *it; - } - std::cout << std::endl; - return (0); -} - -*/ +////////////////////////////////////////////////////////////////////////////// +// +// original main +// +// #include +// #include +// #include +// #if 1 //CREATE A REAL STL EXAMPLE +// #include +// #include +// #include +// namespace ft = std; +// #else +// #include +// #include +// #include +// #endif +// +// #include +// +// #define MAX_RAM 4294967296 +// #define BUFFER_SIZE 4096 +// struct Buffer +// { +// int idx; +// char buff[BUFFER_SIZE]; +// }; +// +// +// #define COUNT (MAX_RAM / (int)sizeof(Buffer)) +// +// template +// class MutantStack : public ft::stack +// { +// public: +// MutantStack() {} +// MutantStack(const MutantStack& src) { *this = src; } +// MutantStack& operator=(const MutantStack& rhs) +// { +// this->c = rhs.c; +// return *this; +// } +// ~MutantStack() {} +// +// typedef typename ft::stack::container_type::iterator iterator; +// +// iterator begin() { return this->c.begin(); } +// iterator end() { return this->c.end(); } +// }; +// +// int main(int argc, char** argv) { +// if (argc != 2) +// { +// std::cerr << "Usage: ./test seed" << std::endl; +// std::cerr << "Provide a seed please" << std::endl; +// std::cerr << "Count value:" << COUNT << std::endl; +// return 1; +// } +// const int seed = atoi(argv[1]); +// srand(seed); +// +// ft::vector vector_str; +// ft::vector vector_int; +// ft::stack stack_int; +// ft::vector vector_buffer; +// ft::stack > stack_deq_buffer; +// ft::map map_int; +// +// for (int i = 0; i < COUNT; i++) +// { +// vector_buffer.push_back(Buffer()); +// } +// +// for (int i = 0; i < COUNT; i++) +// { +// const int idx = rand() % COUNT; +// vector_buffer[idx].idx = 5; +// } +// ft::vector().swap(vector_buffer); +// +// try +// { +// for (int i = 0; i < COUNT; i++) +// { +// const int idx = rand() % COUNT; +// vector_buffer.at(idx); +// std::cerr << "Error: THIS VECTOR SHOULD BE EMPTY!!" < copy = map_int; +// } +// MutantStack iterable_stack; +// for (char letter = 'a'; letter <= 'z'; letter++) +// iterable_stack.push(letter); +// for (MutantStack::iterator it = iterable_stack.begin(); it != iterable_stack.end(); it++) +// { +// std::cout << *it; +// } +// std::cout << std::endl; +// return (0); +// } +// +////////////////////////////////////////////////////////////////////////////// From 99f67b808c533c2668bfddef2f7fe52d31f7558f Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 1 Jun 2022 15:41:14 +0200 Subject: [PATCH 04/53] first implementation, badly, of allocator --- Makefile | 6 ++- headers/ftvector.hpp | 34 +++++++++++++++++ headers/tests.h | 1 + main.cpp | 16 ++++++++ srcs/ftvector.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 2 deletions(-) create mode 100644 headers/ftvector.hpp create mode 100644 srcs/ftvector.cpp diff --git a/Makefile b/Makefile index 4a2a272..5adac0e 100644 --- a/Makefile +++ b/Makefile @@ -19,11 +19,13 @@ LIBS = INCLUDES = -I$(D_HEADERS) D_SRCS = srcs -SRCS = main.cpp +SRCS = main.cpp \ + ftvector.cpp D_HEADERS = headers HEADERS = colors.h \ - tests.h + tests.h \ + ftvector.hpp D_OBJS = builds OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) diff --git a/headers/ftvector.hpp b/headers/ftvector.hpp new file mode 100644 index 0000000..155ad15 --- /dev/null +++ b/headers/ftvector.hpp @@ -0,0 +1,34 @@ +#ifndef FTVECTOR_HPP +# define FTVECTOR_HPP + +# include "colors.h" +# include +# include +# include // std::allocator + +class ftvector { + +public: + + ftvector(); + ftvector( ftvector const & src ); + ~ftvector(); + ftvector & operator=( ftvector const & rhs ); + + unsigned int size() const; + void push_back(const int & element); + +private: + + unsigned int _size; + int * _mem_ptr; + std::allocator _allocator; + +// static std::string const ftvector::_bar; + +}; + +//std::ostream & operator<<(std::ostream & o, ftvector const & rhs); + +#endif + diff --git a/headers/tests.h b/headers/tests.h index 12a747e..c4cd145 100644 --- a/headers/tests.h +++ b/headers/tests.h @@ -2,6 +2,7 @@ # define TESTS_H #include +#include # define TEST(s) \ {\ diff --git a/main.cpp b/main.cpp index 656e66a..8253b47 100644 --- a/main.cpp +++ b/main.cpp @@ -4,9 +4,24 @@ #include "tests.h" #include +#include "ftvector.hpp" int main() { + TEST(vector::vector (constructor)) + { + ftvector myvector; + int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; + int size = sizeof(myint) / sizeof(myint[0]); + + for (int i = 0; i < size; i++) + myvector.push_back (myint[i]); + + std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n"; + } + TESTEND + +/* TEST(vector::vector (constructor)) { // constructors used in the same order as described above: @@ -445,6 +460,7 @@ int main() { myvector.get_allocator().deallocate(p,5); } TESTEND +*/ // execute tests and print them : diff --git a/srcs/ftvector.cpp b/srcs/ftvector.cpp new file mode 100644 index 0000000..a566614 --- /dev/null +++ b/srcs/ftvector.cpp @@ -0,0 +1,90 @@ +/* ************************************************************************** */ +/* */ +/* ::: :::::::: */ +/* ftvector.cpp :+: :+: :+: */ +/* +:+ +:+ +:+ */ +/* By: simplonco +#+ +:+ +#+ */ +/* +#+#+#+#+#+ +#+ */ +/* Created: 2022/06/01 15:39:26 by simplonco #+# #+# */ +/* Updated: 2022/06/01 15:39:57 by simplonco ### ########.fr */ +/* */ +/* ************************************************************************** */ + +#include "ftvector.hpp" + +#define COPLIEN_COLOR B_CYAN + +/********************************************* + * CONSTRUCTORS + *********************************************/ + +ftvector::ftvector() : +_size(0) { +// std::cout << COPLIEN_COLOR "ftvector constructor" RESET "\n"; + _allocator = std::allocator(); + return; +} + +ftvector::ftvector( ftvector const & src ) { +// std::cout << COPLIEN_COLOR "ftvector copy constructor" RESET "\n"; + *this = src; + return; +} + +/********************************************* + * DESTRUCTORS + *********************************************/ + +ftvector::~ftvector() { +// std::cout << COPLIEN_COLOR "ftvector destructor" RESET "\n"; + return; +} + +/********************************************* + * OPERATORS + *********************************************/ + +ftvector & ftvector::operator=( ftvector const & rhs ) { +// Base::operator=(rhs); + if ( this != &rhs ) + { + _size = rhs.size(); + } + return *this; +} + +//std::ostream & operator<<(std::ostream & o, ftvector const & rhs) +//{ +// o << rhs.getFoo(); +// return (o); +//} + +/********************************************* + * ACCESSORS + *********************************************/ + +unsigned int ftvector::size() const {return _size;} + +/********************************************* + * PUBLIC MEMBER FUNCTIONS + *********************************************/ + +void ftvector::push_back(const int & element) { + _mem_ptr = _allocator.allocate(1); + _allocator.construct(_mem_ptr, element); + _size++; +} + +/********************************************* + * NESTED CLASS + *********************************************/ + +//void ftvector::Class::function() {} + +/********************************************* + * STATICS + *********************************************/ + +//std::string const ftvector::_bar = "bar"; + + From f765779b27c61a22e7ba9d1b9dafc55baf763f11 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 1 Jun 2022 20:20:05 +0200 Subject: [PATCH 05/53] wip added all prototypes of members of vector --- headers/ftvector.hpp | 85 +++++++++++++++++++++++++++++++++++++++++--- srcs/ftvector.cpp | 46 ++++++++++++++++-------- 2 files changed, 111 insertions(+), 20 deletions(-) diff --git a/headers/ftvector.hpp b/headers/ftvector.hpp index 155ad15..eace0eb 100644 --- a/headers/ftvector.hpp +++ b/headers/ftvector.hpp @@ -15,17 +15,92 @@ public: ~ftvector(); ftvector & operator=( ftvector const & rhs ); - unsigned int size() const; - void push_back(const int & element); + + /************* + * iterators : + *************/ + // begin +// iterator begin(); +// const_iterator begin() const; + // end +// iterator end(); +// const_iterator end() const; + // rbegin +// reverse_iterator rbegin(); +// const_reverse_iterator rbegin() const; + // rend +// reverse_iterator rend(); +// const_reverse_iterator rend() const; + + /************ + * capacity : + ************/ + // size + // TMP + unsigned int size() const; + // TMP END +// size_type size() const; + // max_size +// size_type max_size() const; + // resize +// void resize(size_type n, value_type val = value_type()); + // capacity + size_type capacity() const; + // empty +// bool empty() const; + //reserve +// void reserve(size_type n); + + /****************** + * element access : + ******************/ + // operator[] +// reference operator[](size_type n); +// const_reference operator[](size_type n) const; + // at +// reference at(size_type n); +// const_reference at(size_type n) const; + // front +// reference front(); +// const_reference front() const; + // back +// reference back(); +// const_reference back() const; + + /************* + * modifiers : + *************/ + // assign +// template +// void assign(InputIterator first, InputIterator last); +// void assign(size_type n, const value_type& val); + // push_back + // TMP + void push_back(const int & element); + // TMP END +// void push_back(const value_type& val); + // pop_back +// void pop_back(); + // insert +// iterator insert(iterator position, const value_type& val); +// void insert(iterator position, size_type n, const value_type& val); +// template +// void insert(iterator position, InputIterator first, InputIterator last); + // erase +// iterator erase(iterator position); +// iterator erase(iterator first, iterator last); + // swap +// void swap(vector& x); + // clear +// void clear(); + private: - unsigned int _size; + std::size_t _size; int * _mem_ptr; std::allocator _allocator; -// static std::string const ftvector::_bar; - }; //std::ostream & operator<<(std::ostream & o, ftvector const & rhs); diff --git a/srcs/ftvector.cpp b/srcs/ftvector.cpp index a566614..fcc3e95 100644 --- a/srcs/ftvector.cpp +++ b/srcs/ftvector.cpp @@ -1,14 +1,3 @@ -/* ************************************************************************** */ -/* */ -/* ::: :::::::: */ -/* ftvector.cpp :+: :+: :+: */ -/* +:+ +:+ +:+ */ -/* By: simplonco +#+ +:+ +#+ */ -/* +#+#+#+#+#+ +#+ */ -/* Created: 2022/06/01 15:39:26 by simplonco #+# #+# */ -/* Updated: 2022/06/01 15:39:57 by simplonco ### ########.fr */ -/* */ -/* ************************************************************************** */ #include "ftvector.hpp" @@ -18,8 +7,9 @@ * CONSTRUCTORS *********************************************/ -ftvector::ftvector() : -_size(0) { +ftvector::ftvector() +: _size(0) +, _space(0) { // std::cout << COPLIEN_COLOR "ftvector constructor" RESET "\n"; _allocator = std::allocator(); return; @@ -70,9 +60,35 @@ unsigned int ftvector::size() const {return _size;} *********************************************/ void ftvector::push_back(const int & element) { - _mem_ptr = _allocator.allocate(1); - _allocator.construct(_mem_ptr, element); + if (_size == _space) + hold_space(1); + _allocator.construct(&_mem_ptr[_size], element); _size++; + + for (unsigned int i = 0; i < _size; i++) + std::cout << _mem_ptr[i] << "\n"; + std::cout << "\n"; + +} + +/********************************************* + * PRIVATE MEMBER FUNCTIONS + *********************************************/ + +void hold_space(std::size_t add_space) { + + if (add_space == 0) + return ; + + int * tmp_ptr; + + if (_space > 0 && add_space == 1) + { + add_space = _space * 2; + } + + tmp_ptr = _allocator.allocate(add_space); + // _mem_ptr = _allocator.allocate(add_space); } /********************************************* From 0146ebcbf13a5b0093d78e2a03c01cafb5eb424a Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 1 Jun 2022 22:05:23 +0200 Subject: [PATCH 06/53] working typedef --- headers/ftvector.hpp | 25 ++++++++++++------------- srcs/ftvector.cpp | 36 ++++++++++++++++++------------------ 2 files changed, 30 insertions(+), 31 deletions(-) diff --git a/headers/ftvector.hpp b/headers/ftvector.hpp index eace0eb..b33673e 100644 --- a/headers/ftvector.hpp +++ b/headers/ftvector.hpp @@ -4,12 +4,17 @@ # include "colors.h" # include # include + # include // std::allocator class ftvector { public: + typedef int value_type; + typedef std::allocator allocator_type; + typedef std::size_t size_type; + ftvector(); ftvector( ftvector const & src ); ~ftvector(); @@ -36,20 +41,17 @@ public: * capacity : ************/ // size - // TMP - unsigned int size() const; - // TMP END -// size_type size() const; + size_type size() const; // max_size // size_type max_size() const; // resize // void resize(size_type n, value_type val = value_type()); // capacity - size_type capacity() const; +// size_type capacity() const; // empty // bool empty() const; //reserve -// void reserve(size_type n); + void reserve(size_type n); /****************** * element access : @@ -75,10 +77,7 @@ public: // void assign(InputIterator first, InputIterator last); // void assign(size_type n, const value_type& val); // push_back - // TMP - void push_back(const int & element); - // TMP END -// void push_back(const value_type& val); + void push_back(const value_type & val); // pop_back // void pop_back(); // insert @@ -97,9 +96,9 @@ public: private: - std::size_t _size; - int * _mem_ptr; - std::allocator _allocator; + size_type _size; + value_type * _mem_ptr; + allocator_type _allocator; }; diff --git a/srcs/ftvector.cpp b/srcs/ftvector.cpp index fcc3e95..4cee4ac 100644 --- a/srcs/ftvector.cpp +++ b/srcs/ftvector.cpp @@ -9,9 +9,10 @@ ftvector::ftvector() : _size(0) -, _space(0) { +//, _space(0) +{ // std::cout << COPLIEN_COLOR "ftvector constructor" RESET "\n"; - _allocator = std::allocator(); + _allocator = allocator_type(); return; } @@ -53,42 +54,41 @@ ftvector & ftvector::operator=( ftvector const & rhs ) { * ACCESSORS *********************************************/ -unsigned int ftvector::size() const {return _size;} +ftvector::size_type ftvector::size() const {return _size;} /********************************************* * PUBLIC MEMBER FUNCTIONS *********************************************/ -void ftvector::push_back(const int & element) { - if (_size == _space) - hold_space(1); +void ftvector::push_back(const value_type & element) { +// if (_size == _space) + reserve(1); _allocator.construct(&_mem_ptr[_size], element); _size++; - for (unsigned int i = 0; i < _size; i++) + for (size_type i = 0; i < _size; i++) std::cout << _mem_ptr[i] << "\n"; std::cout << "\n"; - } /********************************************* * PRIVATE MEMBER FUNCTIONS *********************************************/ -void hold_space(std::size_t add_space) { +void ftvector::reserve(size_type add_space) { if (add_space == 0) return ; - int * tmp_ptr; - - if (_space > 0 && add_space == 1) - { - add_space = _space * 2; - } - - tmp_ptr = _allocator.allocate(add_space); - // _mem_ptr = _allocator.allocate(add_space); +// int * tmp_ptr; +// +// if (_space > 0 && add_space == 1) +// { +// add_space = _space * 2; +// } +// +// tmp_ptr = _allocator.allocate(add_space); + _mem_ptr = _allocator.allocate(15); } /********************************************* From dea7818dfadef08767fb66760ec7cc4d269aa03d Mon Sep 17 00:00:00 2001 From: hugogogo Date: Thu, 2 Jun 2022 18:18:38 +0200 Subject: [PATCH 07/53] push back is working --- Makefile | 1 + headers/ftvector.hpp | 1 + srcs/ftvector.cpp | 49 +++++++++++++++++++++++++++----------------- 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 5adac0e..328f842 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ EXT = cpp CFLAGS = -Wall -Wextra -Werror $(INCLUDES) CFLAGS += -std=c++98 +CFLAGS += -g3 VPATH = $(D_SRCS) diff --git a/headers/ftvector.hpp b/headers/ftvector.hpp index b33673e..fc3ac77 100644 --- a/headers/ftvector.hpp +++ b/headers/ftvector.hpp @@ -97,6 +97,7 @@ public: private: size_type _size; + size_type _capacity; value_type * _mem_ptr; allocator_type _allocator; diff --git a/srcs/ftvector.cpp b/srcs/ftvector.cpp index 4cee4ac..82a09fe 100644 --- a/srcs/ftvector.cpp +++ b/srcs/ftvector.cpp @@ -9,7 +9,8 @@ ftvector::ftvector() : _size(0) -//, _space(0) +, _capacity(0) +, _mem_ptr(NULL) { // std::cout << COPLIEN_COLOR "ftvector constructor" RESET "\n"; _allocator = allocator_type(); @@ -61,8 +62,10 @@ ftvector::size_type ftvector::size() const {return _size;} *********************************************/ void ftvector::push_back(const value_type & element) { -// if (_size == _space) - reserve(1); + if (_size >= _capacity) + { + reserve(std::min(_size + 1, _allocator.max_size() / 2) * 2); + } _allocator.construct(&_mem_ptr[_size], element); _size++; @@ -71,26 +74,34 @@ void ftvector::push_back(const value_type & element) { std::cout << "\n"; } +void ftvector::reserve(size_type new_cap) { + value_type * tmp_ptr; + + if (new_cap > _allocator.max_size()) + throw std::length_error("new_cap > max_size"); + if (_capacity == _allocator.max_size()) + throw std::length_error("capacity == max_size"); + if (new_cap <= _capacity) + return ; + + _capacity = new_cap; + tmp_ptr = _allocator.allocate(new_cap); + + if (_mem_ptr) + { + // TMP + for (size_type i = 0; i < _size; i++) + tmp_ptr[i] = _mem_ptr[i]; + // TMP END + _allocator.deallocate(_mem_ptr, _capacity); + } + _mem_ptr = tmp_ptr; +} + /********************************************* * PRIVATE MEMBER FUNCTIONS *********************************************/ -void ftvector::reserve(size_type add_space) { - - if (add_space == 0) - return ; - -// int * tmp_ptr; -// -// if (_space > 0 && add_space == 1) -// { -// add_space = _space * 2; -// } -// -// tmp_ptr = _allocator.allocate(add_space); - _mem_ptr = _allocator.allocate(15); -} - /********************************************* * NESTED CLASS *********************************************/ From 6362a50ffaded3d145a9d35bf1195f2993688564 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Thu, 2 Jun 2022 19:41:34 +0200 Subject: [PATCH 08/53] little formating improvement --- headers/ftvector.hpp | 110 ++++++++++++++++++++++--------------------- srcs/ftvector.cpp | 83 +++++++++++++++++++++++++------- 2 files changed, 122 insertions(+), 71 deletions(-) diff --git a/headers/ftvector.hpp b/headers/ftvector.hpp index fc3ac77..bfda8fe 100644 --- a/headers/ftvector.hpp +++ b/headers/ftvector.hpp @@ -15,6 +15,8 @@ public: typedef std::allocator allocator_type; typedef std::size_t size_type; + typedef int * iterator; + ftvector(); ftvector( ftvector const & src ); ~ftvector(); @@ -24,74 +26,74 @@ public: /************* * iterators : *************/ - // begin -// iterator begin(); -// const_iterator begin() const; - // end -// iterator end(); -// const_iterator end() const; - // rbegin -// reverse_iterator rbegin(); -// const_reverse_iterator rbegin() const; - // rend -// reverse_iterator rend(); -// const_reverse_iterator rend() const; +// begin ------------------------------------- + iterator begin(); + //const_iterator begin() const; +// end --------------------------------------- + iterator end(); + //const_iterator end() const; +// rbegin ------------------------------------ + //reverse_iterator rbegin(); + //const_reverse_iterator rbegin() const; +// rend -------------------------------------- + //reverse_iterator rend(); + //const_reverse_iterator rend() const; /************ * capacity : ************/ - // size +// size -------------------------------------- size_type size() const; - // max_size -// size_type max_size() const; - // resize -// void resize(size_type n, value_type val = value_type()); - // capacity -// size_type capacity() const; - // empty -// bool empty() const; - //reserve +// max_size ---------------------------------- + //size_type max_size() const; +// resize ------------------------------------ + //void resize(size_type n, value_type val = value_type()); +// capacity ---------------------------------- + //size_type capacity() const; +// empty ------------------------------------- + //bool empty() const; +// reserve ----------------------------------- void reserve(size_type n); /****************** * element access : ******************/ - // operator[] -// reference operator[](size_type n); -// const_reference operator[](size_type n) const; - // at -// reference at(size_type n); -// const_reference at(size_type n) const; - // front -// reference front(); -// const_reference front() const; - // back -// reference back(); -// const_reference back() const; +// operator[] -------------------------------- + //reference operator[](size_type n); + //const_reference operator[](size_type n) const; +// at ---------------------------------------- + //reference at(size_type n); + //const_reference at(size_type n) const; +// front ------------------------------------- + //reference front(); + //const_reference front() const; +// back -------------------------------------- + //reference back(); + //const_reference back() const; /************* * modifiers : *************/ - // assign -// template -// void assign(InputIterator first, InputIterator last); -// void assign(size_type n, const value_type& val); - // push_back +// assign ------------------------------------ + //template + // void assign(InputIterator first, InputIterator last); + //void assign(size_type n, const value_type& val); +// push_back --------------------------------- void push_back(const value_type & val); - // pop_back -// void pop_back(); - // insert -// iterator insert(iterator position, const value_type& val); -// void insert(iterator position, size_type n, const value_type& val); -// template -// void insert(iterator position, InputIterator first, InputIterator last); - // erase -// iterator erase(iterator position); -// iterator erase(iterator first, iterator last); - // swap -// void swap(vector& x); - // clear -// void clear(); +// pop_back ---------------------------------- + //void pop_back(); +// insert ------------------------------------ + //iterator insert(iterator position, const value_type& val); + //void insert(iterator position, size_type n, const value_type& val); + //template + // void insert(iterator position, InputIterator first, InputIterator last); +// erase ------------------------------------- + //iterator erase(iterator position); + //iterator erase(iterator first, iterator last); +// swap -------------------------------------- + //void swap(vector& x); +// clear ------------------------------------- + //void clear(); private: @@ -101,6 +103,8 @@ private: value_type * _mem_ptr; allocator_type _allocator; + void _destroy(iterator first, iterator last); + }; //std::ostream & operator<<(std::ostream & o, ftvector const & rhs); diff --git a/srcs/ftvector.cpp b/srcs/ftvector.cpp index 82a09fe..30c00d6 100644 --- a/srcs/ftvector.cpp +++ b/srcs/ftvector.cpp @@ -51,31 +51,35 @@ ftvector & ftvector::operator=( ftvector const & rhs ) { // return (o); //} -/********************************************* - * ACCESSORS - *********************************************/ - -ftvector::size_type ftvector::size() const {return _size;} /********************************************* * PUBLIC MEMBER FUNCTIONS *********************************************/ -void ftvector::push_back(const value_type & element) { - if (_size >= _capacity) - { - reserve(std::min(_size + 1, _allocator.max_size() / 2) * 2); - } - _allocator.construct(&_mem_ptr[_size], element); - _size++; - - for (size_type i = 0; i < _size; i++) - std::cout << _mem_ptr[i] << "\n"; - std::cout << "\n"; -} + /************* + * iterators : + *************/ +// begin ------------------------------------- +ftvector::iterator ftvector::begin() {return _mem_ptr;} +// end --------------------------------------- +ftvector::iterator ftvector::end() {return &_mem_ptr[_size];} +// rbegin ------------------------------------ +// rend -------------------------------------- + /************ + * capacity : + ************/ +// size -------------------------------------- +ftvector::size_type ftvector::size() const {return _size;} +// max_size ---------------------------------- +// resize ------------------------------------ +// capacity ---------------------------------- +// empty ------------------------------------- +// reserve ----------------------------------- void ftvector::reserve(size_type new_cap) { value_type * tmp_ptr; + iterator first = begin(); + iterator last = end(); if (new_cap > _allocator.max_size()) throw std::length_error("new_cap > max_size"); @@ -89,19 +93,62 @@ void ftvector::reserve(size_type new_cap) { if (_mem_ptr) { - // TMP + // TMP replacing assign() for (size_type i = 0; i < _size; i++) tmp_ptr[i] = _mem_ptr[i]; // TMP END + _destroy(first, last); _allocator.deallocate(_mem_ptr, _capacity); } _mem_ptr = tmp_ptr; } + /****************** + * element access : + ******************/ +// operator[] -------------------------------- +// at ---------------------------------------- +// front ------------------------------------- +// back -------------------------------------- + + /************* + * modifiers : + *************/ +// assign ------------------------------------ +// push_back --------------------------------- +void ftvector::push_back(const value_type & element) { + if (_size >= _capacity) + reserve(std::min(_size + 1, _allocator.max_size() / 2) * 2); + _allocator.construct(&_mem_ptr[_size], element); + _size++; + + // TMP + for (size_type i = 0; i < _size; i++) + std::cout << _mem_ptr[i] << "\n"; + std::cout << "\n"; + // TMP END +} +// pop_back ---------------------------------- +// insert ------------------------------------ +// erase ------------------------------------- +// swap -------------------------------------- +// clear ------------------------------------- + + + + /********************************************* * PRIVATE MEMBER FUNCTIONS *********************************************/ +void ftvector::_destroy(iterator first, iterator last) { + while (first != last) + { + _allocator.destroy(first); + first++; + } +} + /********************************************* * NESTED CLASS *********************************************/ From aecd2caa1cf020a84ffd883735344ad814e5870d Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 3 Jun 2022 14:49:22 +0200 Subject: [PATCH 09/53] add namespace, make stl, and template allocator --- Makefile | 80 +++++++++--- headers/{tests.h => tests.hpp} | 0 headers/{ftvector.hpp => vector.hpp} | 54 ++++++-- srcs/ftvector.cpp => templates/vector.tpp | 56 ++++---- main.cpp => tests/main.cpp | 151 ++-------------------- tests/main42.cpp | 118 +++++++++++++++++ 6 files changed, 262 insertions(+), 197 deletions(-) rename headers/{tests.h => tests.hpp} (100%) rename headers/{ftvector.hpp => vector.hpp} (69%) rename srcs/ftvector.cpp => templates/vector.tpp (66%) rename main.cpp => tests/main.cpp (77%) create mode 100644 tests/main42.cpp diff --git a/Makefile b/Makefile index 328f842..4182658 100644 --- a/Makefile +++ b/Makefile @@ -1,40 +1,72 @@ +# - - - - - - - # +# # +# COLORS # +# # +# - - - - - - - # + +GRAY = "\e[0;30m" +RED = "\e[0;31m" +GREEN = "\e[0;32m" +YELLOW = "\e[0;33m" +BLUE = "\e[0;34m" +PURPLE = "\e[0;35m" +CYAN = "\e[0;36m" +WHITE = "\e[0;37m" + +B_GRAY = "\e[1;30m" +B_RED = "\e[1;31m" +B_GREEN = "\e[1;32m" +B_YELLOW = "\e[1;33m" +B_BLUE = "\e[1;34m" +B_PURPLE = "\e[1;35m" +B_CYAN = "\e[1;36m" +B_WHITE = "\e[1;37m" + +RESET = "\e[0m" + # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # . name = value \ . += append to a variable # # VARIABLES . value . != set result of command # # . name is case sensitive . ?= set if not already set # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # -NAME = containers +NAME = containers -CC = c++ -EXT = cpp +CC = c++ +EXT = cpp -CFLAGS = -Wall -Wextra -Werror $(INCLUDES) -CFLAGS += -std=c++98 -CFLAGS += -g3 +CFLAGS = -Wall -Wextra -Werror $(INCLUDES) +CFLAGS += -std=c++98 +CFLAGS += -g3 -VPATH = $(D_SRCS) +VPATH = $(D_SRCS) -LIBS = +LIBS = -INCLUDES = -I$(D_HEADERS) +F_INCLUDES = $(HEADERS:%=$(D_HEADERS)/%) \ + $(TEMPLATES:%=$(D_TEMPLATES)/%) +INCLUDES = -I$(D_HEADERS) \ + -I$(D_TEMPLATES) -D_SRCS = srcs -SRCS = main.cpp \ - ftvector.cpp +D_SRCS = ./tests +SRCS = main.cpp +#SRCS = main42.cpp -D_HEADERS = headers -HEADERS = colors.h \ - tests.h \ - ftvector.hpp +D_HEADERS = ./headers +HEADERS = colors.h \ + tests.hpp \ + vector.hpp -D_OBJS = builds -OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) +D_TEMPLATES = ./templates +TEMPLATES = vector.tpp + +D_OBJS = builds +OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) ifeq "$(D_OBJS)" "." - RM_OBJS = rm -f $(OBJS) + RM_OBJS = rm -f $(OBJS) else - RM_OBJS = rm -rf $(D_OBJS) + RM_OBJS = rm -rf $(D_OBJS) endif @@ -46,15 +78,21 @@ endif all: $(NAME) +stl: CFLAGS += -D STL +stl: all +ft: all + $(D_OBJS)/%.o: %.$(EXT) | $(D_OBJS) + @echo $(CYAN)"compilation (objects.o) :"$(RESET) $(CC) $(CFLAGS) -c $< -o $@ $(D_OBJS): mkdir $@ -$(OBJS): $(HEADERS:%=$(D_HEADERS)/%) +$(OBJS): $(F_INCLUDES) $(NAME): $(OBJS) + @echo $(CYAN)"linkage (link objects.o) :"$(RESET) $(CC) $(OBJS) -o $@ $(LIBS) leaks: $(NAME) diff --git a/headers/tests.h b/headers/tests.hpp similarity index 100% rename from headers/tests.h rename to headers/tests.hpp diff --git a/headers/ftvector.hpp b/headers/vector.hpp similarity index 69% rename from headers/ftvector.hpp rename to headers/vector.hpp index bfda8fe..a4a720e 100644 --- a/headers/ftvector.hpp +++ b/headers/vector.hpp @@ -1,26 +1,48 @@ -#ifndef FTVECTOR_HPP -# define FTVECTOR_HPP +#ifndef VECTOR_HPP +# define VECTOR_HPP # include "colors.h" # include # include -# include // std::allocator +# include // std::allocator +# include // std::min -class ftvector { +namespace ft { + +template < + class T, + class Allocator = std::allocator +> class vector { public: - typedef int value_type; - typedef std::allocator allocator_type; - typedef std::size_t size_type; + typedef T value_type; + typedef Allocator allocator_type; + typedef std::size_t size_type; - typedef int * iterator; + typedef T * iterator; - ftvector(); - ftvector( ftvector const & src ); - ~ftvector(); - ftvector & operator=( ftvector const & rhs ); + typedef typename allocator_type::reference reference; + + + /************ + * copliens : + ************/ +// constructor ------------------------------- +// explicit vector (const allocator_type& alloc = allocator_type()); +// explicit vector (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()); +// template +// vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); +// vector (const vector& x); + // TMP + vector(); + vector( vector const & src ); + // TMP END +// destructor -------------------------------- + ~vector(); +// operator= --------------------------------- + vector & operator=( vector const & rhs ); /************* @@ -59,7 +81,7 @@ public: * element access : ******************/ // operator[] -------------------------------- - //reference operator[](size_type n); + reference operator[](size_type n); //const_reference operator[](size_type n) const; // at ---------------------------------------- //reference at(size_type n); @@ -107,7 +129,11 @@ private: }; -//std::ostream & operator<<(std::ostream & o, ftvector const & rhs); +//std::ostream & operator<<(std::ostream & o, vector const & rhs); + +} + +# include "vector.tpp" #endif diff --git a/srcs/ftvector.cpp b/templates/vector.tpp similarity index 66% rename from srcs/ftvector.cpp rename to templates/vector.tpp index 30c00d6..e95cdc0 100644 --- a/srcs/ftvector.cpp +++ b/templates/vector.tpp @@ -1,24 +1,28 @@ -#include "ftvector.hpp" +//#include "vector.hpp" #define COPLIEN_COLOR B_CYAN +namespace ft { + /********************************************* * CONSTRUCTORS *********************************************/ -ftvector::ftvector() +template +vector::vector() : _size(0) , _capacity(0) , _mem_ptr(NULL) { -// std::cout << COPLIEN_COLOR "ftvector constructor" RESET "\n"; +// std::cout << COPLIEN_COLOR "vector constructor" RESET "\n"; _allocator = allocator_type(); return; } -ftvector::ftvector( ftvector const & src ) { -// std::cout << COPLIEN_COLOR "ftvector copy constructor" RESET "\n"; +template +vector::vector( vector const & src ) { +// std::cout << COPLIEN_COLOR "vector copy constructor" RESET "\n"; *this = src; return; } @@ -27,8 +31,9 @@ ftvector::ftvector( ftvector const & src ) { * DESTRUCTORS *********************************************/ -ftvector::~ftvector() { -// std::cout << COPLIEN_COLOR "ftvector destructor" RESET "\n"; +template +vector::~vector() { +// std::cout << COPLIEN_COLOR "vector destructor" RESET "\n"; return; } @@ -36,7 +41,8 @@ ftvector::~ftvector() { * OPERATORS *********************************************/ -ftvector & ftvector::operator=( ftvector const & rhs ) { +template +vector & vector::operator=( vector const & rhs ) { // Base::operator=(rhs); if ( this != &rhs ) { @@ -45,7 +51,7 @@ ftvector & ftvector::operator=( ftvector const & rhs ) { return *this; } -//std::ostream & operator<<(std::ostream & o, ftvector const & rhs) +//std::ostream & operator<<(std::ostream & o, vector const & rhs) //{ // o << rhs.getFoo(); // return (o); @@ -60,9 +66,11 @@ ftvector & ftvector::operator=( ftvector const & rhs ) { * iterators : *************/ // begin ------------------------------------- -ftvector::iterator ftvector::begin() {return _mem_ptr;} +template +typename vector::iterator vector::begin() {return _mem_ptr;} // end --------------------------------------- -ftvector::iterator ftvector::end() {return &_mem_ptr[_size];} +template +typename vector::iterator vector::end() {return &_mem_ptr[_size];} // rbegin ------------------------------------ // rend -------------------------------------- @@ -70,13 +78,15 @@ ftvector::iterator ftvector::end() {return &_mem_ptr[_size];} * capacity : ************/ // size -------------------------------------- -ftvector::size_type ftvector::size() const {return _size;} +template +typename vector::size_type vector::size() const {return _size;} // max_size ---------------------------------- // resize ------------------------------------ // capacity ---------------------------------- // empty ------------------------------------- // reserve ----------------------------------- -void ftvector::reserve(size_type new_cap) { +template +void vector::reserve(size_type new_cap) { value_type * tmp_ptr; iterator first = begin(); iterator last = end(); @@ -107,6 +117,8 @@ void ftvector::reserve(size_type new_cap) { * element access : ******************/ // operator[] -------------------------------- +template +typename vector::reference vector::operator[](size_type n) {return _mem_ptr[n];} // at ---------------------------------------- // front ------------------------------------- // back -------------------------------------- @@ -116,17 +128,12 @@ void ftvector::reserve(size_type new_cap) { *************/ // assign ------------------------------------ // push_back --------------------------------- -void ftvector::push_back(const value_type & element) { +template +void vector::push_back(const value_type & element) { if (_size >= _capacity) reserve(std::min(_size + 1, _allocator.max_size() / 2) * 2); _allocator.construct(&_mem_ptr[_size], element); _size++; - - // TMP - for (size_type i = 0; i < _size; i++) - std::cout << _mem_ptr[i] << "\n"; - std::cout << "\n"; - // TMP END } // pop_back ---------------------------------- // insert ------------------------------------ @@ -141,7 +148,8 @@ void ftvector::push_back(const value_type & element) { * PRIVATE MEMBER FUNCTIONS *********************************************/ -void ftvector::_destroy(iterator first, iterator last) { +template +void vector::_destroy(iterator first, iterator last) { while (first != last) { _allocator.destroy(first); @@ -153,12 +161,12 @@ void ftvector::_destroy(iterator first, iterator last) { * NESTED CLASS *********************************************/ -//void ftvector::Class::function() {} +//void vector::Class::function() {} /********************************************* * STATICS *********************************************/ -//std::string const ftvector::_bar = "bar"; - +//std::string const vector::_bar = "bar"; +} diff --git a/main.cpp b/tests/main.cpp similarity index 77% rename from main.cpp rename to tests/main.cpp index 8253b47..340d756 100644 --- a/main.cpp +++ b/tests/main.cpp @@ -1,23 +1,31 @@ #include #include #include "colors.h" -#include "tests.h" +#include "tests.hpp" +#include // std::setw() #include -#include "ftvector.hpp" +#ifdef STL + namespace ft = std; +#else + #include "vector.hpp" +#endif int main() { TEST(vector::vector (constructor)) { - ftvector myvector; + ft::vector myvector; int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; int size = sizeof(myint) / sizeof(myint[0]); for (int i = 0; i < size; i++) - myvector.push_back (myint[i]); + myvector.push_back(myint[i]); - std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n"; + for (int i = 0; i < size; i++) + std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; + + std::cout << " -> myvector stores " << int(myvector.size()) << " numbers.\n"; } TESTEND @@ -477,136 +485,3 @@ int main() { return 0; } - - - - - - - - - - - -////////////////////////////////////////////////////////////////////////////// -// -// original main -// -// #include -// #include -// #include -// #if 1 //CREATE A REAL STL EXAMPLE -// #include -// #include -// #include -// namespace ft = std; -// #else -// #include -// #include -// #include -// #endif -// -// #include -// -// #define MAX_RAM 4294967296 -// #define BUFFER_SIZE 4096 -// struct Buffer -// { -// int idx; -// char buff[BUFFER_SIZE]; -// }; -// -// -// #define COUNT (MAX_RAM / (int)sizeof(Buffer)) -// -// template -// class MutantStack : public ft::stack -// { -// public: -// MutantStack() {} -// MutantStack(const MutantStack& src) { *this = src; } -// MutantStack& operator=(const MutantStack& rhs) -// { -// this->c = rhs.c; -// return *this; -// } -// ~MutantStack() {} -// -// typedef typename ft::stack::container_type::iterator iterator; -// -// iterator begin() { return this->c.begin(); } -// iterator end() { return this->c.end(); } -// }; -// -// int main(int argc, char** argv) { -// if (argc != 2) -// { -// std::cerr << "Usage: ./test seed" << std::endl; -// std::cerr << "Provide a seed please" << std::endl; -// std::cerr << "Count value:" << COUNT << std::endl; -// return 1; -// } -// const int seed = atoi(argv[1]); -// srand(seed); -// -// ft::vector vector_str; -// ft::vector vector_int; -// ft::stack stack_int; -// ft::vector vector_buffer; -// ft::stack > stack_deq_buffer; -// ft::map map_int; -// -// for (int i = 0; i < COUNT; i++) -// { -// vector_buffer.push_back(Buffer()); -// } -// -// for (int i = 0; i < COUNT; i++) -// { -// const int idx = rand() % COUNT; -// vector_buffer[idx].idx = 5; -// } -// ft::vector().swap(vector_buffer); -// -// try -// { -// for (int i = 0; i < COUNT; i++) -// { -// const int idx = rand() % COUNT; -// vector_buffer.at(idx); -// std::cerr << "Error: THIS VECTOR SHOULD BE EMPTY!!" < copy = map_int; -// } -// MutantStack iterable_stack; -// for (char letter = 'a'; letter <= 'z'; letter++) -// iterable_stack.push(letter); -// for (MutantStack::iterator it = iterable_stack.begin(); it != iterable_stack.end(); it++) -// { -// std::cout << *it; -// } -// std::cout << std::endl; -// return (0); -// } -// -////////////////////////////////////////////////////////////////////////////// diff --git a/tests/main42.cpp b/tests/main42.cpp new file mode 100644 index 0000000..5d31ace --- /dev/null +++ b/tests/main42.cpp @@ -0,0 +1,118 @@ + +#include +#include +#include +#if 1 //CREATE A REAL STL EXAMPLE + #include + #include + #include + namespace ft = std; +#else + #include + #include + #include +#endif + +#include + +#define MAX_RAM 4294967296 +#define BUFFER_SIZE 4096 +struct Buffer +{ + int idx; + char buff[BUFFER_SIZE]; +}; + + +#define COUNT (MAX_RAM / (int)sizeof(Buffer)) + +template +class MutantStack : public ft::stack +{ +public: + MutantStack() {} + MutantStack(const MutantStack& src) { *this = src; } + MutantStack& operator=(const MutantStack& rhs) + { + this->c = rhs.c; + return *this; + } + ~MutantStack() {} + + typedef typename ft::stack::container_type::iterator iterator; + + iterator begin() { return this->c.begin(); } + iterator end() { return this->c.end(); } +}; + +int main(int argc, char** argv) { + if (argc != 2) + { + std::cerr << "Usage: ./test seed" << std::endl; + std::cerr << "Provide a seed please" << std::endl; + std::cerr << "Count value:" << COUNT << std::endl; + return 1; + } + const int seed = atoi(argv[1]); + srand(seed); + + ft::vector vector_str; + ft::vector vector_int; + ft::stack stack_int; + ft::vector vector_buffer; + ft::stack > stack_deq_buffer; + ft::map map_int; + + for (int i = 0; i < COUNT; i++) + { + vector_buffer.push_back(Buffer()); + } + + for (int i = 0; i < COUNT; i++) + { + const int idx = rand() % COUNT; + vector_buffer[idx].idx = 5; + } + ft::vector().swap(vector_buffer); + + try + { + for (int i = 0; i < COUNT; i++) + { + const int idx = rand() % COUNT; + vector_buffer.at(idx); + std::cerr << "Error: THIS VECTOR SHOULD BE EMPTY!!" < copy = map_int; + } + MutantStack iterable_stack; + for (char letter = 'a'; letter <= 'z'; letter++) + iterable_stack.push(letter); + for (MutantStack::iterator it = iterable_stack.begin(); it != iterable_stack.end(); it++) + { + std::cout << *it; + } + std::cout << std::endl; + return (0); +} + From 7d857c5e4edfbfb27a48502c54441e33f66fb814 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 3 Jun 2022 17:10:53 +0200 Subject: [PATCH 10/53] add capacity() and basic assign() --- headers/vector.hpp | 16 +++---- templates/vector.tpp | 107 +++++++++++++++++++++++++++++++++++-------- tests/main.cpp | 51 +++++++++++++-------- 3 files changed, 127 insertions(+), 47 deletions(-) diff --git a/headers/vector.hpp b/headers/vector.hpp index a4a720e..eb3d652 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -30,15 +30,13 @@ public: * copliens : ************/ // constructor ------------------------------- -// explicit vector (const allocator_type& alloc = allocator_type()); -// explicit vector (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()); + explicit vector (const allocator_type & alloc = allocator_type()); + explicit vector (size_type n, const value_type& val = value_type(), + const allocator_type& alloc = allocator_type()); // template -// vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); -// vector (const vector& x); - // TMP - vector(); +// vector (InputIterator first, InputIterator last, +// const allocator_type& alloc = allocator_type()); vector( vector const & src ); - // TMP END // destructor -------------------------------- ~vector(); // operator= --------------------------------- @@ -71,7 +69,7 @@ public: // resize ------------------------------------ //void resize(size_type n, value_type val = value_type()); // capacity ---------------------------------- - //size_type capacity() const; + size_type capacity() const; // empty ------------------------------------- //bool empty() const; // reserve ----------------------------------- @@ -99,7 +97,7 @@ public: // assign ------------------------------------ //template // void assign(InputIterator first, InputIterator last); - //void assign(size_type n, const value_type& val); + void assign(size_type n, const value_type& val); // push_back --------------------------------- void push_back(const value_type & val); // pop_back ---------------------------------- diff --git a/templates/vector.tpp b/templates/vector.tpp index e95cdc0..9ba3f4c 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -9,19 +9,38 @@ namespace ft { * CONSTRUCTORS *********************************************/ +// template +// vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); + template -vector::vector() +vector:: +vector( const Allocator & alloc ) : _size(0) , _capacity(0) , _mem_ptr(NULL) +, _allocator(alloc) { // std::cout << COPLIEN_COLOR "vector constructor" RESET "\n"; - _allocator = allocator_type(); return; } template -vector::vector( vector const & src ) { +vector:: +vector( size_type n, const T & val, const Allocator & alloc ) +: _size(0) +, _capacity(0) +, _mem_ptr(NULL) +, _allocator(alloc) +{ +// std::cout << COPLIEN_COLOR "vector constructor" RESET "\n"; + assign(n, val); + return; +} + +template +vector:: +vector( vector const & src ) +{ // std::cout << COPLIEN_COLOR "vector copy constructor" RESET "\n"; *this = src; return; @@ -32,7 +51,9 @@ vector::vector( vector const & src ) { *********************************************/ template -vector::~vector() { +vector:: +~vector() +{ // std::cout << COPLIEN_COLOR "vector destructor" RESET "\n"; return; } @@ -42,7 +63,9 @@ vector::~vector() { *********************************************/ template -vector & vector::operator=( vector const & rhs ) { +vector & vector:: +operator=( vector const & rhs ) +{ // Base::operator=(rhs); if ( this != &rhs ) { @@ -67,10 +90,18 @@ vector & vector::operator=( vector const & rhs ) { *************/ // begin ------------------------------------- template -typename vector::iterator vector::begin() {return _mem_ptr;} +typename vector::iterator vector:: +begin() +{ + return _mem_ptr; +} // end --------------------------------------- template -typename vector::iterator vector::end() {return &_mem_ptr[_size];} +typename vector::iterator vector:: +end() +{ + return &_mem_ptr[_size]; +} // rbegin ------------------------------------ // rend -------------------------------------- @@ -79,22 +110,32 @@ typename vector::iterator vector::end() {return &_me ************/ // size -------------------------------------- template -typename vector::size_type vector::size() const {return _size;} +typename vector::size_type vector:: +size( ) const +{ + return _size; +} // max_size ---------------------------------- // resize ------------------------------------ // capacity ---------------------------------- +template +typename vector::size_type vector:: +capacity() const +{ + return _capacity; +} // empty ------------------------------------- // reserve ----------------------------------- template -void vector::reserve(size_type new_cap) { +void vector:: +reserve( size_type new_cap ) +{ value_type * tmp_ptr; - iterator first = begin(); - iterator last = end(); if (new_cap > _allocator.max_size()) - throw std::length_error("new_cap > max_size"); + throw std::length_error("reserve: new_cap > max_size"); if (_capacity == _allocator.max_size()) - throw std::length_error("capacity == max_size"); + throw std::length_error("reserve: capacity == max_size"); if (new_cap <= _capacity) return ; @@ -103,11 +144,11 @@ void vector::reserve(size_type new_cap) { if (_mem_ptr) { - // TMP replacing assign() + // TMP replacing assign(first, last) for (size_type i = 0; i < _size; i++) tmp_ptr[i] = _mem_ptr[i]; // TMP END - _destroy(first, last); + _destroy(begin(), end()); _allocator.deallocate(_mem_ptr, _capacity); } _mem_ptr = tmp_ptr; @@ -118,7 +159,11 @@ void vector::reserve(size_type new_cap) { ******************/ // operator[] -------------------------------- template -typename vector::reference vector::operator[](size_type n) {return _mem_ptr[n];} +typename vector::reference vector:: +operator[](size_type n) +{ + return _mem_ptr[n]; +} // at ---------------------------------------- // front ------------------------------------- // back -------------------------------------- @@ -127,9 +172,33 @@ typename vector::reference vector::operator[](size_t * modifiers : *************/ // assign ------------------------------------ +template +void vector:: +assign( size_type n, const T & val ) +{ + if (n > _allocator.max_size()) + throw std::length_error("assign: n > max_size"); + + value_type * tmp_ptr; + + _destroy(begin(), end()); + if (n > _capacity) + { + _capacity = n; + tmp_ptr = _allocator.allocate(n); + if (_mem_ptr) + _allocator.deallocate(_mem_ptr, _capacity); + _mem_ptr = tmp_ptr; + } + _size = n; + while (n) + _allocator.construct(&_mem_ptr[--n], val); +} // push_back --------------------------------- template -void vector::push_back(const value_type & element) { +void vector:: +push_back( const value_type & element ) +{ if (_size >= _capacity) reserve(std::min(_size + 1, _allocator.max_size() / 2) * 2); _allocator.construct(&_mem_ptr[_size], element); @@ -149,7 +218,9 @@ void vector::push_back(const value_type & element) { *********************************************/ template -void vector::_destroy(iterator first, iterator last) { +void vector:: +_destroy(iterator first, iterator last) +{ while (first != last) { _allocator.destroy(first); diff --git a/tests/main.cpp b/tests/main.cpp index 340d756..f8d9d5e 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -13,19 +13,33 @@ int main() { - TEST(vector::vector (constructor)) - { + TEST(test assign capacity) + { ft::vector myvector; - int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; - int size = sizeof(myint) / sizeof(myint[0]); + int size; + std::cout << "capacity before assignation : " << myvector.capacity() << "\n"; + + std::cout << "\nassign 1\n"; + myvector.assign(1, 12); + size = myvector.size(); for (int i = 0; i < size; i++) - myvector.push_back(myint[i]); + std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; + std::cout << "\nsize :" << size << " , capacity :" << myvector.capacity() << "\n"; + std::cout << "\nassign 3\n"; + myvector.assign(3, 12); + size = myvector.size(); for (int i = 0; i < size; i++) - std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; + std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; + std::cout << "\nsize :" << size << " , capacity :" << myvector.capacity() << "\n"; - std::cout << " -> myvector stores " << int(myvector.size()) << " numbers.\n"; + std::cout << "\nassign 7268\n"; + myvector.assign(7268, 12); + size = myvector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; + std::cout << "\nsize :" << size << " , capacity :" << myvector.capacity() << "\n"; } TESTEND @@ -317,30 +331,27 @@ int main() { std::cout << "Size of third: " << int (third.size()) << '\n'; } TESTEND +*/ TEST(vector::push_back) { - std::vector myvector; + ft::vector myvector; - // original : - // - // int myint; - // std::cout << "Please enter some integers (enter 0 to end):\n"; - // do { - // std::cin >> myint; - // myvector.push_back (myint); - // } while (myint); - // - // replaced by : int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; int size = sizeof(myint) / sizeof(myint[0]); for (int i = 0; i < size; i++) - myvector.push_back (myint[i]); + myvector.push_back(myint[i]); + + for (int i = 0; i < size; i++) + std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; + + std::cout << " -> myvector stores " << int(myvector.size()) << " numbers.\n"; + - std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n"; } TESTEND +/* TEST(vector::pop_back) { std::vector myvector; From 556807669efb7c581d2977994ddfea3449de46d5 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 3 Jun 2022 19:49:09 +0200 Subject: [PATCH 11/53] fix push_back reserve growth --- headers/vector.hpp | 15 ++--- templates/vector.tpp | 153 +++++++++++++++++++++++++++---------------- tests/main.cpp | 35 ++++++---- 3 files changed, 125 insertions(+), 78 deletions(-) diff --git a/headers/vector.hpp b/headers/vector.hpp index eb3d652..5e793cc 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -33,9 +33,9 @@ public: explicit vector (const allocator_type & alloc = allocator_type()); explicit vector (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()); -// template -// vector (InputIterator first, InputIterator last, -// const allocator_type& alloc = allocator_type()); + template + vector (InputIterator first, InputIterator last, + const allocator_type& alloc = allocator_type()); vector( vector const & src ); // destructor -------------------------------- ~vector(); @@ -95,8 +95,8 @@ public: * modifiers : *************/ // assign ------------------------------------ - //template - // void assign(InputIterator first, InputIterator last); + template + void assign(InputIterator first, InputIterator last); void assign(size_type n, const value_type& val); // push_back --------------------------------- void push_back(const value_type & val); @@ -113,7 +113,7 @@ public: // swap -------------------------------------- //void swap(vector& x); // clear ------------------------------------- - //void clear(); + void clear(); private: @@ -129,9 +129,8 @@ private: //std::ostream & operator<<(std::ostream & o, vector const & rhs); -} +} // namespace ft # include "vector.tpp" #endif - diff --git a/templates/vector.tpp b/templates/vector.tpp index 9ba3f4c..6314167 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -1,7 +1,6 @@ -//#include "vector.hpp" - -#define COPLIEN_COLOR B_CYAN +#define VT_TPL template +#define VT vector namespace ft { @@ -9,39 +8,41 @@ namespace ft { * CONSTRUCTORS *********************************************/ -// template -// vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type()); - -template -vector:: +VT_TPL VT:: vector( const Allocator & alloc ) : _size(0) , _capacity(0) , _mem_ptr(NULL) , _allocator(alloc) { -// std::cout << COPLIEN_COLOR "vector constructor" RESET "\n"; return; } -template -vector:: +VT_TPL VT:: vector( size_type n, const T & val, const Allocator & alloc ) : _size(0) , _capacity(0) , _mem_ptr(NULL) , _allocator(alloc) { -// std::cout << COPLIEN_COLOR "vector constructor" RESET "\n"; assign(n, val); return; } -template -vector:: +VT_TPL template VT:: + vector(InputIterator first, InputIterator last, const Allocator & alloc) +: _size(0) +, _capacity(0) +, _mem_ptr(NULL) +, _allocator(alloc) +{ + assign(first, last); + return; +} + +VT_TPL VT:: vector( vector const & src ) { -// std::cout << COPLIEN_COLOR "vector copy constructor" RESET "\n"; *this = src; return; } @@ -50,11 +51,9 @@ vector( vector const & src ) * DESTRUCTORS *********************************************/ -template -vector:: +VT_TPL VT:: ~vector() { -// std::cout << COPLIEN_COLOR "vector destructor" RESET "\n"; return; } @@ -62,8 +61,7 @@ vector:: * OPERATORS *********************************************/ -template -vector & vector:: +VT_TPL VT & VT:: operator=( vector const & rhs ) { // Base::operator=(rhs); @@ -89,46 +87,44 @@ operator=( vector const & rhs ) * iterators : *************/ // begin ------------------------------------- -template -typename vector::iterator vector:: -begin() -{ - return _mem_ptr; -} +VT_TPL typename VT::iterator VT:: + begin() { return _mem_ptr; } +//const_iterator begin() const; // end --------------------------------------- -template -typename vector::iterator vector:: -end() -{ - return &_mem_ptr[_size]; -} +VT_TPL typename VT::iterator VT:: + end() { return &_mem_ptr[_size]; } +//const_iterator end() const; // rbegin ------------------------------------ +//reverse_iterator rbegin(); +//const_reverse_iterator rbegin() const; // rend -------------------------------------- +//reverse_iterator rend(); +//const_reverse_iterator rend() const; /************ * capacity : ************/ // size -------------------------------------- -template -typename vector::size_type vector:: -size( ) const +VT_TPL typename VT::size_type VT:: + size( ) const { return _size; } // max_size ---------------------------------- +//size_type max_size() const; // resize ------------------------------------ +//void resize(size_type n, value_type val = value_type()); // capacity ---------------------------------- -template -typename vector::size_type vector:: -capacity() const +VT_TPL typename VT::size_type VT:: + capacity() const { return _capacity; } // empty ------------------------------------- +//bool empty() const; // reserve ----------------------------------- -template -void vector:: -reserve( size_type new_cap ) +VT_TPL void VT:: + reserve( size_type new_cap ) { value_type * tmp_ptr; @@ -158,23 +154,44 @@ reserve( size_type new_cap ) * element access : ******************/ // operator[] -------------------------------- -template -typename vector::reference vector:: -operator[](size_type n) -{ - return _mem_ptr[n]; -} +VT_TPL typename VT::reference VT:: + operator[](size_type n) { return _mem_ptr[n]; } +//const_reference operator[](size_type n) const; // at ---------------------------------------- +//reference at(size_type n); +//const_reference at(size_type n) const; // front ------------------------------------- +//reference front(); +//const_reference front() const; // back -------------------------------------- +//reference back(); +//const_reference back() const; /************* * modifiers : *************/ // assign ------------------------------------ -template -void vector:: -assign( size_type n, const T & val ) +VT_TPL template void VT:: + assign( InputIterator first, InputIterator last) +{ + InputIterator tmp = first; + int range; + + clear(); + + for (range = 1; tmp != last; range++) + tmp++; + _size += range; + if (_size >= _capacity) + reserve(_size); + while (first != last) + { + _allocator.construct(&_mem_ptr[_size], first); + first++; + } +} +VT_TPL void VT:: + assign( size_type n, const T & val ) { if (n > _allocator.max_size()) throw std::length_error("assign: n > max_size"); @@ -195,20 +212,38 @@ assign( size_type n, const T & val ) _allocator.construct(&_mem_ptr[--n], val); } // push_back --------------------------------- -template -void vector:: -push_back( const value_type & element ) +VT_TPL void VT:: + push_back( const value_type & element ) { if (_size >= _capacity) - reserve(std::min(_size + 1, _allocator.max_size() / 2) * 2); + { + if (_size == 0) + reserve(1); + else + reserve(std::min(_size * 2, _allocator.max_size())); + } _allocator.construct(&_mem_ptr[_size], element); _size++; } // pop_back ---------------------------------- +//void pop_back(); // insert ------------------------------------ +//iterator insert(iterator position, const value_type& val); +//void insert(iterator position, size_type n, const value_type& val); +//template +// void insert(iterator position, InputIterator first, InputIterator last); // erase ------------------------------------- +//iterator erase(iterator position); +//iterator erase(iterator first, iterator last); // swap -------------------------------------- +//void swap(vector& x); // clear ------------------------------------- +VT_TPL void VT:: + clear() +{ + _destroy(begin(), end()); + _size = 0; +} @@ -217,9 +252,8 @@ push_back( const value_type & element ) * PRIVATE MEMBER FUNCTIONS *********************************************/ -template -void vector:: -_destroy(iterator first, iterator last) +VT_TPL void VT:: + _destroy(iterator first, iterator last) { while (first != last) { @@ -240,4 +274,7 @@ _destroy(iterator first, iterator last) //std::string const vector::_bar = "bar"; -} +} // namespace ft + +#undef VT +#undef VT_TPL diff --git a/tests/main.cpp b/tests/main.cpp index f8d9d5e..8f0f5b0 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -25,21 +25,21 @@ int main() { size = myvector.size(); for (int i = 0; i < size; i++) std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; - std::cout << "\nsize :" << size << " , capacity :" << myvector.capacity() << "\n"; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; std::cout << "\nassign 3\n"; myvector.assign(3, 12); size = myvector.size(); for (int i = 0; i < size; i++) std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; - std::cout << "\nsize :" << size << " , capacity :" << myvector.capacity() << "\n"; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - std::cout << "\nassign 7268\n"; - myvector.assign(7268, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; - std::cout << "\nsize :" << size << " , capacity :" << myvector.capacity() << "\n"; + // std::cout << "\nassign 7268\n"; + // myvector.assign(7268, 12); + // size = myvector.size(); + // for (int i = 0; i < size; i++) + // std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; + // std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; } TESTEND @@ -337,17 +337,28 @@ int main() { { ft::vector myvector; + // first test int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; int size = sizeof(myint) / sizeof(myint[0]); for (int i = 0; i < size; i++) + { myvector.push_back(myint[i]); - + std::cout << "[capacity : " + << std::setw(2) << myvector.capacity() << "] " + << myvector[i] << "\n"; + } for (int i = 0; i < size; i++) std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; + std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; - std::cout << " -> myvector stores " << int(myvector.size()) << " numbers.\n"; - - + // second test + // for (int i = 0; i < 72363; i++) + // { + // myvector.push_back(9); + // std::cout << "[" << i + // << ":" << myvector.capacity() << "] "; + // } + // std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; } TESTEND From a4550a9bb9b073ff1b512e86289c55bc77c995f7 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sat, 4 Jun 2022 10:57:57 +0200 Subject: [PATCH 12/53] save before closing pc --- headers/tests.hpp | 3 +++ templates/vector.tpp | 2 ++ tests/main.cpp | 62 ++++++++++++++++++++++---------------------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/headers/tests.hpp b/headers/tests.hpp index c4cd145..a5d2675 100644 --- a/headers/tests.hpp +++ b/headers/tests.hpp @@ -1,6 +1,7 @@ #ifndef TESTS_H # define TESTS_H +#include "colors.h" #include #include @@ -17,6 +18,8 @@ test_list.push_back(test);\ } +# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; + struct test_base { std::string title; virtual void func() {} diff --git a/templates/vector.tpp b/templates/vector.tpp index 6314167..8552b31 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -174,6 +174,7 @@ VT_TPL typename VT::reference VT:: VT_TPL template void VT:: assign( InputIterator first, InputIterator last) { +std::cout << "inside assign(first, last)"; InputIterator tmp = first; int range; @@ -193,6 +194,7 @@ VT_TPL template void VT:: VT_TPL void VT:: assign( size_type n, const T & val ) { +std::cout << "inside assign(n, val)"; if (n > _allocator.max_size()) throw std::length_error("assign: n > max_size"); diff --git a/tests/main.cpp b/tests/main.cpp index 8f0f5b0..c4cd456 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -13,36 +13,6 @@ int main() { - TEST(test assign capacity) - { - ft::vector myvector; - int size; - - std::cout << "capacity before assignation : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 1\n"; - myvector.assign(1, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 3\n"; - myvector.assign(3, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - // std::cout << "\nassign 7268\n"; - // myvector.assign(7268, 12); - // size = myvector.size(); - // for (int i = 0; i < size; i++) - // std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << " - "; - // std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - } - TESTEND - /* TEST(vector::vector (constructor)) { @@ -309,9 +279,12 @@ int main() { std::cout << "myvector.front() is now " << myvector.front() << '\n'; } TESTEND +*/ TEST(vector::assign) { + TITLE(cplusplus.com reference :) + std::vector first; std::vector second; std::vector third; @@ -329,9 +302,36 @@ int main() { std::cout << "Size of first: " << int (first.size()) << '\n'; std::cout << "Size of second: " << int (second.size()) << '\n'; std::cout << "Size of third: " << int (third.size()) << '\n'; + + TITLE(capacity tests of assignation :) + + ft::vector myvector; + int size; + + std::cout << "capacity before assignation : " << myvector.capacity() << "\n"; + + std::cout << "\nassign 1\n"; + myvector.assign(1, 12); + size = myvector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << myvector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; + + std::cout << "\nassign 3\n"; + myvector.assign(3, 12); + size = myvector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << myvector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; + + // std::cout << "\nassign 7268\n"; + // myvector.assign(7268, 12); + // size = myvector.size(); + // for (int i = 0; i < size; i++) + // std::cout << "[" << i << "] " << myvector[i] << " - "; + // std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; } TESTEND -*/ TEST(vector::push_back) { From 647b6eee254a2d51611507cf6e59b4673f0a289e Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sun, 5 Jun 2022 13:26:53 +0200 Subject: [PATCH 13/53] save before closing pc --- templates/vector.tpp | 1 + tests/main.cpp | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/templates/vector.tpp b/templates/vector.tpp index 8552b31..0dde9e9 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -191,6 +191,7 @@ std::cout << "inside assign(first, last)"; first++; } } + VT_TPL void VT:: assign( size_type n, const T & val ) { diff --git a/tests/main.cpp b/tests/main.cpp index c4cd456..4b5d322 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -33,6 +33,7 @@ int main() { } TESTEND + TEST(vector::=operator) { std::vector foo (3,0); @@ -46,6 +47,7 @@ int main() { } TESTEND + TEST(vector::begin) { std::vector myvector; @@ -58,6 +60,7 @@ int main() { } TESTEND + TEST(vector::end) { std::vector myvector; @@ -70,6 +73,7 @@ int main() { } TESTEND + TEST(vector::rbegin) { std::vector myvector (5); // 5 default-constructed ints @@ -87,6 +91,7 @@ int main() { } TESTEND + TEST(vector::rend) { std::vector myvector (5); // 5 default-constructed ints @@ -104,6 +109,7 @@ int main() { } TESTEND + TEST(vector::size) { std::vector myints; @@ -120,6 +126,7 @@ int main() { } TESTEND + TEST(vector::max_size) { std::vector myvector; @@ -133,6 +140,7 @@ int main() { } TESTEND + TEST(vector::resize) { std::vector myvector; @@ -151,6 +159,7 @@ int main() { } TESTEND + TEST(vector::capacity) { std::vector myvector; @@ -164,6 +173,7 @@ int main() { } TESTEND + TEST(vector::empty) { std::vector myvector; @@ -181,6 +191,7 @@ int main() { } TESTEND + TEST(vector::reserve) { std::vector::size_type sz; @@ -210,6 +221,7 @@ int main() { } TESTEND + TEST(vector::operator[]) { std::vector myvector (10); // 10 zero-initialized elements @@ -235,6 +247,7 @@ int main() { } TESTEND + TEST(vector::at) { std::vector myvector (10); // 10 zero-initialized ints @@ -250,6 +263,7 @@ int main() { } TESTEND + TEST(vector::front) { std::vector myvector; @@ -265,6 +279,7 @@ int main() { } TESTEND + TEST(vector::back) { std::vector myvector; @@ -333,6 +348,8 @@ int main() { } TESTEND + +/* TEST(vector::push_back) { ft::vector myvector; @@ -361,6 +378,8 @@ int main() { // std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; } TESTEND +*/ + /* TEST(vector::pop_back) From 8c232df3753afe09f3433c3b07d1ef90a4a6c207 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 8 Jun 2022 15:24:44 +0200 Subject: [PATCH 14/53] assign sfinae is integral detection --- Makefile | 3 +- headers/enable_if.hpp | 16 ++++++ headers/is_integral.hpp | 116 ++++++++++++++++++++++++++++++++++++++++ headers/vector.hpp | 12 ++++- templates/vector.tpp | 14 +++-- 5 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 headers/enable_if.hpp create mode 100644 headers/is_integral.hpp diff --git a/Makefile b/Makefile index 4182658..db9cec5 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ RESET = "\e[0m" NAME = containers -CC = c++ +CC = clang++ EXT = cpp CFLAGS = -Wall -Wextra -Werror $(INCLUDES) @@ -55,6 +55,7 @@ SRCS = main.cpp D_HEADERS = ./headers HEADERS = colors.h \ tests.hpp \ + enable_if.hpp \ vector.hpp D_TEMPLATES = ./templates diff --git a/headers/enable_if.hpp b/headers/enable_if.hpp new file mode 100644 index 0000000..655ee96 --- /dev/null +++ b/headers/enable_if.hpp @@ -0,0 +1,16 @@ +#ifndef ENABLE_IF_HPP +# define ENABLE_IF_HPP + +namespace ft { + +template +struct enable_if {}; + + +template +struct enable_if { typedef T type; }; + +} // namespace ft + +#endif + diff --git a/headers/is_integral.hpp b/headers/is_integral.hpp new file mode 100644 index 0000000..e6cb782 --- /dev/null +++ b/headers/is_integral.hpp @@ -0,0 +1,116 @@ +#ifndef IS_INTEGRAL_HPP +# define IS_INTEGRAL_HPP + +namespace ft { + +//struct true_type { +// typedef bool value_type; +// typedef true_type type; +// static const bool value = true; +//}; +// +//struct false_type { +// typedef T value_type; +// typedef false_type type; +// static const bool value = false; +//}; + +template struct is_integral +{ + typedef char yes[1]; + typedef yes no[2]; + + static T type; + +// integral types : https://www.cplusplus.com/reference/type_traits/is_integral/ + static yes& test(bool); + static yes& test(char); +// static yes& test(char16_t); +// static yes& test(char32_t); + static yes& test(wchar_t); + static yes& test(signed char); + static yes& test(short int); + static yes& test(int); + static yes& test(long int); + static yes& test(long long int); + static yes& test(unsigned char); + static yes& test(unsigned short int); + static yes& test(unsigned int); + static yes& test(unsigned long int); + static yes& test(unsigned long long int); + +/* + static yes& test(const bool); + static yes& test(const char); + static yes& test(const wchar_t); + static yes& test(const signed char); + static yes& test(const short int); + static yes& test(const int); + static yes& test(const long int); + static yes& test(const long long int); + static yes& test(const unsigned char); + static yes& test(const unsigned short int); + static yes& test(const unsigned int); + static yes& test(const unsigned long int); + static yes& test(const unsigned long long int); + + static yes& test(volatile bool); + static yes& test(volatile char); + static yes& test(volatile wchar_t); + static yes& test(volatile signed char); + static yes& test(volatile short int); + static yes& test(volatile int); + static yes& test(volatile long int); + static yes& test(volatile long long int); + static yes& test(volatile unsigned char); + static yes& test(volatile unsigned short int); + static yes& test(volatile unsigned int); + static yes& test(volatile unsigned long int); + static yes& test(volatile unsigned long long int); + + static yes& test(const volatile bool); + static yes& test(const volatile char); + static yes& test(const volatile wchar_t); + static yes& test(const volatile signed char); + static yes& test(const volatile short int); + static yes& test(const volatile int); + static yes& test(const volatile long int); + static yes& test(const volatile long long int); + static yes& test(const volatile unsigned char); + static yes& test(const volatile unsigned short int); + static yes& test(const volatile unsigned int); + static yes& test(const volatile unsigned long int); + static yes& test(const volatile unsigned long long int); +*/ + + + // non-template function with direct matching are always considered first + // then the function template with direct matching are considered + // https://stackoverflow.com/questions/12877546/how-do-i-avoid-implicit-conversions-on + template static no& test(C); + + static const bool value = sizeof(test(type)) == sizeof(yes); +}; + +} // namespace ft + +// "template <>" introduce a total specialization of a template : +// +// template +// class A +// { +// // body for the general case +// }; +// +// template <> +// class A +// { +// // body that only applies for T = bool +// }; +// +// https://stackoverflow.com/questions/6288812/what-is-the-meaning-of-template-with-empty-angle-brackets-in-c + +// SFINAE : https://jguegant.github.io/blogs/tech/sfinae-introduction.html + +#endif + diff --git a/headers/vector.hpp b/headers/vector.hpp index 5e793cc..53ed939 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -4,9 +4,10 @@ # include "colors.h" # include # include - # include // std::allocator # include // std::min +# include "enable_if.hpp" +# include "is_integral.hpp" namespace ft { @@ -96,7 +97,14 @@ public: *************/ // assign ------------------------------------ template - void assign(InputIterator first, InputIterator last); + typename enable_if< !is_integral::value,void >::type + assign(InputIterator first, InputIterator last); + // template + // void assign(InputIterator first, InputIterator last + // typename enable_if< !is_integral::value, bool >::type == true); +// template +// typename enable_if< is_integral::value,void >::type +// assign(size_type n, const value_type& val); void assign(size_type n, const value_type& val); // push_back --------------------------------- void push_back(const value_type & val); diff --git a/templates/vector.tpp b/templates/vector.tpp index 0dde9e9..fe48257 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -171,10 +171,13 @@ VT_TPL typename VT::reference VT:: * modifiers : *************/ // assign ------------------------------------ -VT_TPL template void VT:: +VT_TPL template +typename enable_if< !is_integral::value,void >::type VT:: assign( InputIterator first, InputIterator last) { -std::cout << "inside assign(first, last)"; +// TMP +std::cout << B_RED "inside assign(first, last) " RESET; +// TMP END InputIterator tmp = first; int range; @@ -192,10 +195,15 @@ std::cout << "inside assign(first, last)"; } } +// VT_TPL typename enable_if< isinteger::value,std::string >::type VT:: +//VT_TPL template +//typename enable_if< is_integral::value,void >::type VT:: VT_TPL void VT:: assign( size_type n, const T & val ) { -std::cout << "inside assign(n, val)"; +// TMP +std::cout << B_RED "inside assign(n, val) " RESET; +// TMP END if (n > _allocator.max_size()) throw std::length_error("assign: n > max_size"); From 5d0e631cb77c151e77935f3c784047be2005916b Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 8 Jun 2022 20:54:44 +0200 Subject: [PATCH 15/53] add tests for vector assign iterator, and tests script --- Makefile | 6 ++-- headers/is_integral.hpp | 70 -------------------------------------- headers/vector.hpp | 8 +---- templates/vector.tpp | 30 ++++++++--------- tests/main.cpp | 74 ++++++++++++++++++++++++++++++----------- tests/test.sh | 10 ++++++ 6 files changed, 82 insertions(+), 116 deletions(-) create mode 100644 tests/test.sh diff --git a/Makefile b/Makefile index db9cec5..ccb02b8 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ RESET = "\e[0m" NAME = containers -CC = clang++ +CC = g++ EXT = cpp CFLAGS = -Wall -Wextra -Werror $(INCLUDES) @@ -80,8 +80,8 @@ endif all: $(NAME) stl: CFLAGS += -D STL -stl: all -ft: all +stl: re +ft: re $(D_OBJS)/%.o: %.$(EXT) | $(D_OBJS) @echo $(CYAN)"compilation (objects.o) :"$(RESET) diff --git a/headers/is_integral.hpp b/headers/is_integral.hpp index e6cb782..8a70806 100644 --- a/headers/is_integral.hpp +++ b/headers/is_integral.hpp @@ -3,18 +3,6 @@ namespace ft { -//struct true_type { -// typedef bool value_type; -// typedef true_type type; -// static const bool value = true; -//}; -// -//struct false_type { -// typedef T value_type; -// typedef false_type type; -// static const bool value = false; -//}; - template struct is_integral { typedef char yes[1]; @@ -39,51 +27,6 @@ template struct is_integral static yes& test(unsigned long int); static yes& test(unsigned long long int); -/* - static yes& test(const bool); - static yes& test(const char); - static yes& test(const wchar_t); - static yes& test(const signed char); - static yes& test(const short int); - static yes& test(const int); - static yes& test(const long int); - static yes& test(const long long int); - static yes& test(const unsigned char); - static yes& test(const unsigned short int); - static yes& test(const unsigned int); - static yes& test(const unsigned long int); - static yes& test(const unsigned long long int); - - static yes& test(volatile bool); - static yes& test(volatile char); - static yes& test(volatile wchar_t); - static yes& test(volatile signed char); - static yes& test(volatile short int); - static yes& test(volatile int); - static yes& test(volatile long int); - static yes& test(volatile long long int); - static yes& test(volatile unsigned char); - static yes& test(volatile unsigned short int); - static yes& test(volatile unsigned int); - static yes& test(volatile unsigned long int); - static yes& test(volatile unsigned long long int); - - static yes& test(const volatile bool); - static yes& test(const volatile char); - static yes& test(const volatile wchar_t); - static yes& test(const volatile signed char); - static yes& test(const volatile short int); - static yes& test(const volatile int); - static yes& test(const volatile long int); - static yes& test(const volatile long long int); - static yes& test(const volatile unsigned char); - static yes& test(const volatile unsigned short int); - static yes& test(const volatile unsigned int); - static yes& test(const volatile unsigned long int); - static yes& test(const volatile unsigned long long int); -*/ - - // non-template function with direct matching are always considered first // then the function template with direct matching are considered // https://stackoverflow.com/questions/12877546/how-do-i-avoid-implicit-conversions-on @@ -95,19 +38,6 @@ template struct is_integral } // namespace ft // "template <>" introduce a total specialization of a template : -// -// template -// class A -// { -// // body for the general case -// }; -// -// template <> -// class A -// { -// // body that only applies for T = bool -// }; -// // https://stackoverflow.com/questions/6288812/what-is-the-meaning-of-template-with-empty-angle-brackets-in-c // SFINAE : https://jguegant.github.io/blogs/tech/sfinae-introduction.html diff --git a/headers/vector.hpp b/headers/vector.hpp index 53ed939..e4b3540 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -99,17 +99,11 @@ public: template typename enable_if< !is_integral::value,void >::type assign(InputIterator first, InputIterator last); - // template - // void assign(InputIterator first, InputIterator last - // typename enable_if< !is_integral::value, bool >::type == true); -// template -// typename enable_if< is_integral::value,void >::type -// assign(size_type n, const value_type& val); void assign(size_type n, const value_type& val); // push_back --------------------------------- void push_back(const value_type & val); // pop_back ---------------------------------- - //void pop_back(); + void pop_back(); // insert ------------------------------------ //iterator insert(iterator position, const value_type& val); //void insert(iterator position, size_type n, const value_type& val); diff --git a/templates/vector.tpp b/templates/vector.tpp index fe48257..69c756b 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -155,7 +155,10 @@ VT_TPL void VT:: ******************/ // operator[] -------------------------------- VT_TPL typename VT::reference VT:: - operator[](size_type n) { return _mem_ptr[n]; } + operator[](size_type n) +{ + return _mem_ptr[n]; +} //const_reference operator[](size_type n) const; // at ---------------------------------------- //reference at(size_type n); @@ -175,35 +178,25 @@ VT_TPL template typename enable_if< !is_integral::value,void >::type VT:: assign( InputIterator first, InputIterator last) { -// TMP -std::cout << B_RED "inside assign(first, last) " RESET; -// TMP END InputIterator tmp = first; - int range; + int range = 0; clear(); - for (range = 1; tmp != last; range++) - tmp++; + while (tmp++ != last) + range++; _size += range; if (_size >= _capacity) reserve(_size); while (first != last) { - _allocator.construct(&_mem_ptr[_size], first); + _allocator.construct(&_mem_ptr[_size], *first); first++; } } - -// VT_TPL typename enable_if< isinteger::value,std::string >::type VT:: -//VT_TPL template -//typename enable_if< is_integral::value,void >::type VT:: VT_TPL void VT:: assign( size_type n, const T & val ) { -// TMP -std::cout << B_RED "inside assign(n, val) " RESET; -// TMP END if (n > _allocator.max_size()) throw std::length_error("assign: n > max_size"); @@ -237,7 +230,12 @@ VT_TPL void VT:: _size++; } // pop_back ---------------------------------- -//void pop_back(); +VT_TPL void VT:: + pop_back() +{ + _allocator.destroy(end() - 1); + _size--; +} // insert ------------------------------------ //iterator insert(iterator position, const value_type& val); //void insert(iterator position, size_type n, const value_type& val); diff --git a/tests/main.cpp b/tests/main.cpp index 4b5d322..bed6c7a 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -298,15 +298,16 @@ int main() { TEST(vector::assign) { + // title TITLE(cplusplus.com reference :) - std::vector first; - std::vector second; - std::vector third; + ft::vector first; + ft::vector second; + ft::vector third; first.assign (7,100); // 7 ints with a value of 100 - std::vector::iterator it; + ft::vector::iterator it; it=first.begin()+1; second.assign (it,first.end()-1); // the 5 central values of first @@ -318,6 +319,8 @@ int main() { std::cout << "Size of second: " << int (second.size()) << '\n'; std::cout << "Size of third: " << int (third.size()) << '\n'; + + // title TITLE(capacity tests of assignation :) ft::vector myvector; @@ -339,17 +342,50 @@ int main() { std::cout << "[" << i << "] " << myvector[i] << " - "; std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - // std::cout << "\nassign 7268\n"; - // myvector.assign(7268, 12); - // size = myvector.size(); - // for (int i = 0; i < size; i++) - // std::cout << "[" << i << "] " << myvector[i] << " - "; - // std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; + std::cout << "\nassign 7268\n"; + myvector.assign(7268, 12); + size = myvector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << myvector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; + + + // title + TITLE(tests of iterators :) + + ft::vector int_vector_1; + ft::vector int_vector_2; + ft::vector int_vector_3; + ft::vector it_vector; + + std::cout << "\nassign 1\n"; + int_vector_1.assign(1, 12); + it_vector.assign(int_vector_1.begin(), int_vector_1.end()); + size = it_vector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << it_vector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << it_vector.capacity() << "\n"; + + std::cout << "\nassign 1\n"; + int_vector_2.assign(1, 6); + it_vector.assign(int_vector_2.begin(), int_vector_2.end() - 1); + size = it_vector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << it_vector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << it_vector.capacity() << "\n"; + + std::cout << "\nassign 1\n"; + int_vector_3.assign(266, 1); + it_vector.assign(int_vector_3.begin() + 13, int_vector_3.end() - 172); + size = it_vector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << it_vector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << it_vector.capacity() << "\n"; + } TESTEND -/* TEST(vector::push_back) { ft::vector myvector; @@ -369,17 +405,15 @@ int main() { std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; // second test - // for (int i = 0; i < 72363; i++) - // { - // myvector.push_back(9); - // std::cout << "[" << i - // << ":" << myvector.capacity() << "] "; - // } - // std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; + for (int i = 0; i < 72363; i++) + { + myvector.push_back(9); + std::cout << "[" << i + << ":" << myvector.capacity() << "] "; + } + std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; } TESTEND -*/ - /* TEST(vector::pop_back) diff --git a/tests/test.sh b/tests/test.sh new file mode 100644 index 0000000..f180752 --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# cd $(dirname $0) + +make stl > /dev/null +./containers > tests/output_stl.log + +make ft > /dev/null +./containers > tests/output_ft.log + +diff --context=0 --color=always tests/output_stl.log tests/output_ft.log From b385f6220a0b6b5df8d087062ad81a1c4097a62c Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 8 Jun 2022 21:17:39 +0200 Subject: [PATCH 16/53] resolved pbm assign iterator --- templates/vector.tpp | 8 ++++---- tests/main.cpp | 25 ++++++++++++------------- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/templates/vector.tpp b/templates/vector.tpp index 69c756b..5f6959d 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -179,19 +179,19 @@ typename enable_if< !is_integral::value,void >::type VT:: assign( InputIterator first, InputIterator last) { InputIterator tmp = first; - int range = 0; + unsigned int range = 0; clear(); while (tmp++ != last) range++; - _size += range; - if (_size >= _capacity) - reserve(_size); + if (range >= _capacity) + reserve(range); while (first != last) { _allocator.construct(&_mem_ptr[_size], *first); first++; + _size++; } } VT_TPL void VT:: diff --git a/tests/main.cpp b/tests/main.cpp index bed6c7a..bd8ee50 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -319,7 +319,6 @@ int main() { std::cout << "Size of second: " << int (second.size()) << '\n'; std::cout << "Size of third: " << int (third.size()) << '\n'; - // title TITLE(capacity tests of assignation :) @@ -357,31 +356,31 @@ int main() { ft::vector int_vector_2; ft::vector int_vector_3; ft::vector it_vector; + int ssize; std::cout << "\nassign 1\n"; int_vector_1.assign(1, 12); it_vector.assign(int_vector_1.begin(), int_vector_1.end()); - size = it_vector.size(); - for (int i = 0; i < size; i++) + ssize = it_vector.size(); + for (int i = 0; i < ssize; i++) std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << it_vector.capacity() << "\n"; + std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - std::cout << "\nassign 1\n"; + std::cout << "\nassign 0\n"; int_vector_2.assign(1, 6); it_vector.assign(int_vector_2.begin(), int_vector_2.end() - 1); - size = it_vector.size(); - for (int i = 0; i < size; i++) + ssize = it_vector.size(); + for (int i = 0; i < ssize; i++) std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << it_vector.capacity() << "\n"; + std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - std::cout << "\nassign 1\n"; + std::cout << "\nassign 266 - 13 - 172 = 81\n"; int_vector_3.assign(266, 1); it_vector.assign(int_vector_3.begin() + 13, int_vector_3.end() - 172); - size = it_vector.size(); - for (int i = 0; i < size; i++) + ssize = it_vector.size(); + for (int i = 0; i < ssize; i++) std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << it_vector.capacity() << "\n"; - + std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; } TESTEND From 8326f7f28355e9e68b79ff384544c593870fc908 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Thu, 9 Jun 2022 14:14:13 +0200 Subject: [PATCH 17/53] added resize and _increment_capacity --- headers/vector.hpp | 52 ++++++---- templates/vector.tpp | 211 ++++++++++++++++++++++------------------- tests/main.cpp | 220 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 348 insertions(+), 135 deletions(-) diff --git a/headers/vector.hpp b/headers/vector.hpp index e4b3540..4816261 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -1,11 +1,14 @@ #ifndef VECTOR_HPP # define VECTOR_HPP -# include "colors.h" # include # include # include // std::allocator # include // std::min +# include // out_of_range, length_error, logic_error +# include // NULL, size_t, ptrdiff_t + +# include "colors.h" # include "enable_if.hpp" # include "is_integral.hpp" @@ -13,24 +16,34 @@ namespace ft { template < class T, - class Allocator = std::allocator -> class vector { + class Allocator = std::allocator > +class vector { public: - typedef T value_type; - typedef Allocator allocator_type; - typedef std::size_t size_type; + typedef T value_type; + typedef Allocator allocator_type; + typedef std::size_t size_type; +// typedef std::ptrdiff_t difference_type; - typedef T * iterator; + typedef T * iterator; + typedef T const * const_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; - typedef typename allocator_type::reference reference; /************ * copliens : ************/ -// constructor ------------------------------- +// constructors ------------------------------ explicit vector (const allocator_type & alloc = allocator_type()); explicit vector (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type()); @@ -66,13 +79,13 @@ public: // size -------------------------------------- size_type size() const; // max_size ---------------------------------- - //size_type max_size() const; + size_type max_size() const; // resize ------------------------------------ - //void resize(size_type n, value_type val = value_type()); + void resize(size_type n, value_type val = value_type()); // capacity ---------------------------------- size_type capacity() const; // empty ------------------------------------- - //bool empty() const; + bool empty() const; // reserve ----------------------------------- void reserve(size_type n); @@ -81,16 +94,16 @@ public: ******************/ // operator[] -------------------------------- reference operator[](size_type n); - //const_reference operator[](size_type n) const; + const_reference operator[](size_type n) const; // at ---------------------------------------- - //reference at(size_type n); - //const_reference at(size_type n) const; + reference at(size_type n); + const_reference at(size_type n) const; // front ------------------------------------- - //reference front(); - //const_reference front() const; + reference front(); + const_reference front() const; // back -------------------------------------- - //reference back(); - //const_reference back() const; + reference back(); + const_reference back() const; /************* * modifiers : @@ -126,6 +139,7 @@ private: allocator_type _allocator; void _destroy(iterator first, iterator last); + void _increment_capacity(size_type n); }; diff --git a/templates/vector.tpp b/templates/vector.tpp index 5f6959d..03e030b 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -5,66 +5,52 @@ namespace ft { /********************************************* - * CONSTRUCTORS + * COPLIENS *********************************************/ - +// constructors ------------------------------ VT_TPL VT:: -vector( const Allocator & alloc ) -: _size(0) -, _capacity(0) -, _mem_ptr(NULL) -, _allocator(alloc) -{ + vector( const Allocator & alloc ) + : _size(0) + , _capacity(0) + , _mem_ptr(NULL) + , _allocator(alloc) { + return; } - VT_TPL VT:: -vector( size_type n, const T & val, const Allocator & alloc ) -: _size(0) -, _capacity(0) -, _mem_ptr(NULL) -, _allocator(alloc) -{ + vector( size_type n, const T & val, const Allocator & alloc ) + : _size(0) + , _capacity(0) + , _mem_ptr(NULL) + , _allocator(alloc) { + assign(n, val); return; } - VT_TPL template VT:: vector(InputIterator first, InputIterator last, const Allocator & alloc) -: _size(0) -, _capacity(0) -, _mem_ptr(NULL) -, _allocator(alloc) -{ + : _size(0) + , _capacity(0) + , _mem_ptr(NULL) + , _allocator(alloc) { + assign(first, last); return; } - VT_TPL VT:: -vector( vector const & src ) -{ + vector( vector const & src ) { + *this = src; return; } - -/********************************************* - * DESTRUCTORS - *********************************************/ - +// destructors ------------------------------- VT_TPL VT:: -~vector() -{ - return; -} - -/********************************************* - * OPERATORS - *********************************************/ - + ~vector() { return; } +// operator= --------------------------------- VT_TPL VT & VT:: -operator=( vector const & rhs ) -{ -// Base::operator=(rhs); + operator=( vector const & rhs ) { + + //Base::operator=(rhs); if ( this != &rhs ) { _size = rhs.size(); @@ -72,12 +58,6 @@ operator=( vector const & rhs ) return *this; } -//std::ostream & operator<<(std::ostream & o, vector const & rhs) -//{ -// o << rhs.getFoo(); -// return (o); -//} - /********************************************* * PUBLIC MEMBER FUNCTIONS @@ -106,26 +86,40 @@ VT_TPL typename VT::iterator VT:: ************/ // size -------------------------------------- VT_TPL typename VT::size_type VT:: - size( ) const -{ - return _size; -} + size( ) const { return _size; } // max_size ---------------------------------- -//size_type max_size() const; +VT_TPL typename VT::size_type VT:: + max_size() const { return (_allocator.max_size()); } // resize ------------------------------------ -//void resize(size_type n, value_type val = value_type()); +VT_TPL void VT:: + resize(size_type n, value_type val) { + + if (n > _size) + { + if (n > _capacity) + _increment_capacity(n); + while (_size != n) + { + _allocator.construct(&_mem_ptr[_size], val); + ++_size; + } + } + else if (n < _size) + { + while (_size != n) + _allocator.destroy(&_mem_ptr[--_size]); + } +} // capacity ---------------------------------- VT_TPL typename VT::size_type VT:: - capacity() const -{ - return _capacity; -} + capacity() const { return _capacity; } // empty ------------------------------------- -//bool empty() const; +VT_TPL bool VT:: + empty() const { return (_size == 0); } // reserve ----------------------------------- VT_TPL void VT:: - reserve( size_type new_cap ) -{ + reserve( size_type new_cap ) { + value_type * tmp_ptr; if (new_cap > _allocator.max_size()) @@ -140,10 +134,8 @@ VT_TPL void VT:: if (_mem_ptr) { - // TMP replacing assign(first, last) for (size_type i = 0; i < _size; i++) tmp_ptr[i] = _mem_ptr[i]; - // TMP END _destroy(begin(), end()); _allocator.deallocate(_mem_ptr, _capacity); } @@ -155,20 +147,34 @@ VT_TPL void VT:: ******************/ // operator[] -------------------------------- VT_TPL typename VT::reference VT:: - operator[](size_type n) -{ - return _mem_ptr[n]; -} -//const_reference operator[](size_type n) const; + operator[](size_type n) { return _mem_ptr[n]; } +VT_TPL typename VT::const_reference VT:: + operator[](size_type n) const { return _mem_ptr[n]; } // at ---------------------------------------- -//reference at(size_type n); -//const_reference at(size_type n) const; +VT_TPL typename VT::reference VT:: + at(size_type n) { + + if (n >= _size) + throw std::out_of_range("vector out of range"); + return (_mem_ptr[n]); +} +VT_TPL typename VT::const_reference VT:: + at(size_type n) const { + + if (n >= _size) + throw std::out_of_range("vector out of range"); + return (_mem_ptr[n]); +} // front ------------------------------------- -//reference front(); -//const_reference front() const; +VT_TPL typename VT::reference VT:: + front() { return (*_mem_ptr); } +VT_TPL typename VT::const_reference VT:: + front() const { return (*_mem_ptr); } // back -------------------------------------- -//reference back(); -//const_reference back() const; +VT_TPL typename VT::reference VT:: + back() { return (_mem_ptr[_size - 1]); } +VT_TPL typename VT::const_reference VT:: + back() const { return (_mem_ptr[_size - 1]); } /************* * modifiers : @@ -176,8 +182,8 @@ VT_TPL typename VT::reference VT:: // assign ------------------------------------ VT_TPL template typename enable_if< !is_integral::value,void >::type VT:: - assign( InputIterator first, InputIterator last) -{ + assign( InputIterator first, InputIterator last) { + InputIterator tmp = first; unsigned int range = 0; @@ -186,7 +192,7 @@ typename enable_if< !is_integral::value,void >::type VT:: while (tmp++ != last) range++; if (range >= _capacity) - reserve(range); + _increment_capacity(range); while (first != last) { _allocator.construct(&_mem_ptr[_size], *first); @@ -195,8 +201,8 @@ typename enable_if< !is_integral::value,void >::type VT:: } } VT_TPL void VT:: - assign( size_type n, const T & val ) -{ + assign( size_type n, const T & val ) { + if (n > _allocator.max_size()) throw std::length_error("assign: n > max_size"); @@ -217,25 +223,16 @@ VT_TPL void VT:: } // push_back --------------------------------- VT_TPL void VT:: - push_back( const value_type & element ) -{ + push_back( const value_type & element ) { + if (_size >= _capacity) - { - if (_size == 0) - reserve(1); - else - reserve(std::min(_size * 2, _allocator.max_size())); - } + _increment_capacity(1); _allocator.construct(&_mem_ptr[_size], element); _size++; } // pop_back ---------------------------------- VT_TPL void VT:: - pop_back() -{ - _allocator.destroy(end() - 1); - _size--; -} + pop_back() { _allocator.destroy(end() - 1); _size--; } // insert ------------------------------------ //iterator insert(iterator position, const value_type& val); //void insert(iterator position, size_type n, const value_type& val); @@ -248,11 +245,7 @@ VT_TPL void VT:: //void swap(vector& x); // clear ------------------------------------- VT_TPL void VT:: - clear() -{ - _destroy(begin(), end()); - _size = 0; -} + clear() { _destroy(begin(), end()); _size = 0; } @@ -262,8 +255,8 @@ VT_TPL void VT:: *********************************************/ VT_TPL void VT:: - _destroy(iterator first, iterator last) -{ + _destroy(iterator first, iterator last) { + while (first != last) { _allocator.destroy(first); @@ -271,12 +264,34 @@ VT_TPL void VT:: } } +VT_TPL void VT:: + _increment_capacity(size_type n) { + + size_type res; + + res = std::max(_size * 2, n); + reserve(std::min(res, _allocator.max_size())); +} + + +/********************************************* + * OPERATORS + *********************************************/ + +//std::ostream & operator<<(std::ostream & o, vector const & rhs) +//{ +// o << rhs.getFoo(); +// return (o); +//} + + /********************************************* * NESTED CLASS *********************************************/ //void vector::Class::function() {} + /********************************************* * STATICS *********************************************/ diff --git a/tests/main.cpp b/tests/main.cpp index bd8ee50..eb604ac 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -16,6 +16,9 @@ int main() { /* TEST(vector::vector (constructor)) { + // title + TITLE(cplusplus.com reference :) + // constructors used in the same order as described above: std::vector first; // empty vector of ints std::vector second (4,100); // four ints with value 100 @@ -36,6 +39,9 @@ int main() { TEST(vector::=operator) { + // title + TITLE(cplusplus.com reference :) + std::vector foo (3,0); std::vector bar (5,0); @@ -50,6 +56,9 @@ int main() { TEST(vector::begin) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector; for (int i=1; i<=5; i++) myvector.push_back(i); @@ -63,6 +72,9 @@ int main() { TEST(vector::end) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector; for (int i=1; i<=5; i++) myvector.push_back(i); @@ -76,6 +88,9 @@ int main() { TEST(vector::rbegin) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector (5); // 5 default-constructed ints int i=0; @@ -94,6 +109,9 @@ int main() { TEST(vector::rend) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector (5); // 5 default-constructed ints std::vector::reverse_iterator rit = myvector.rbegin(); @@ -112,6 +130,9 @@ int main() { TEST(vector::size) { + // title + TITLE(cplusplus.com reference :) + std::vector myints; std::cout << "0. size: " << myints.size() << '\n'; @@ -129,6 +150,9 @@ int main() { TEST(vector::max_size) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector; // set some content in the vector: @@ -139,11 +163,15 @@ int main() { std::cout << "max_size: " << myvector.max_size() << "\n"; } TESTEND +*/ TEST(vector::resize) { - std::vector myvector; + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; // set some initial content: for (int i = 1; i < 10; i++) myvector.push_back(i); @@ -156,13 +184,94 @@ int main() { for (unsigned int i = 0; i < myvector.size(); i++) std::cout << ' ' << myvector[i]; std::cout << '\n'; + + + // title + TITLE(test size and capacity 1 :) + + ft::vector vector2; + + std::cout << "size: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "assign(10, 1)\n"; + vector2.assign(10, 1); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(15)\n"; + vector2.resize(15); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(10)\n"; + vector2.resize(10); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(19)\n"; + vector2.resize(19); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(20)\n"; + vector2.resize(20); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(21)\n"; + vector2.resize(21); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + + // title + TITLE(test size and capacity 2 :) + + ft::vector vector3; + + std::cout << "size: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; + + std::cout << "assign(10, 1)\n"; + vector3.assign(10, 1); + for (unsigned int i = 0; i < vector3.size(); i++) + std::cout << "[" << i << "]" << vector3[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; + + std::cout << "resize(21)\n"; + vector3.resize(21); + for (unsigned int i = 0; i < vector3.size(); i++) + std::cout << "[" << i << "]" << vector3[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; } TESTEND TEST(vector::capacity) { - std::vector myvector; + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; // set some content in the vector: for (int i=0; i<100; i++) myvector.push_back(i); @@ -176,8 +285,11 @@ int main() { TEST(vector::empty) { - std::vector myvector; - int sum (0); + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + int sum (0); for (int i=1;i<=10;i++) myvector.push_back(i); @@ -194,9 +306,12 @@ int main() { TEST(vector::reserve) { - std::vector::size_type sz; + // title + TITLE(cplusplus.com reference :) + + ft::vector::size_type sz; + ft::vector foo; - std::vector foo; sz = foo.capacity(); std::cout << "making foo grow:\n"; for (int i=0; i<100; ++i) { @@ -207,7 +322,8 @@ int main() { } } - std::vector bar; + ft::vector bar; + sz = bar.capacity(); bar.reserve(100); // this is the only difference with foo above std::cout << "making bar grow:\n"; @@ -224,9 +340,11 @@ int main() { TEST(vector::operator[]) { - std::vector myvector (10); // 10 zero-initialized elements + // title + TITLE(cplusplus.com reference :) - std::vector::size_type sz = myvector.size(); + ft::vector myvector (10); // 10 zero-initialized elements + ft::vector::size_type sz = myvector.size(); // assign some values: for (unsigned i=0; i myvector (10); // 10 zero-initialized ints + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (10); // 10 zero-initialized ints // assign some values: for (unsigned i=0; i myvector; + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; myvector.push_back(78); myvector.push_back(16); @@ -282,7 +406,10 @@ int main() { TEST(vector::back) { - std::vector myvector; + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; myvector.push_back(78); myvector.push_back(16); @@ -290,11 +417,35 @@ int main() { // now front equals 78, and back 16 myvector.front() -= myvector.back(); - std::cout << "myvector.front() is now " << myvector.front() << '\n'; + + + // title + TITLE(test with negatives :) + + myvector.push_back(236); + myvector.push_back(8973); + + myvector.front() -= myvector.back(); + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + + + // title + TITLE(test with char :) + + ft::vector letters; + letters.push_back('o'); + letters.push_back('m'); + letters.push_back('g'); + letters.push_back('w'); + letters.push_back('t'); + letters.push_back('f'); + + if (!letters.empty()) { + std::cout << "The first character is '" << letters.front() << "'.\n"; + } } TESTEND -*/ TEST(vector::assign) { @@ -387,9 +538,11 @@ int main() { TEST(vector::push_back) { + // title + TITLE(cplusplus.com reference :) + ft::vector myvector; - // first test int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; int size = sizeof(myint) / sizeof(myint[0]); for (int i = 0; i < size; i++) @@ -403,7 +556,10 @@ int main() { std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; - // second test + + // title + TITLE(big push back :) + for (int i = 0; i < 72363; i++) { myvector.push_back(9); @@ -414,11 +570,15 @@ int main() { } TESTEND -/* TEST(vector::pop_back) { - std::vector myvector; + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + int sum (0); + myvector.push_back (100); myvector.push_back (200); myvector.push_back (300); @@ -430,11 +590,23 @@ int main() { } std::cout << "The elements of myvector add up to " << sum << '\n'; + + + // title + TITLE(check state :) + + std::cout << "size : " << myvector.size() << '\n'; + std::cout << "capacity : " << myvector.capacity() << '\n'; } TESTEND + +/* TEST(vector::insert) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector (3,100); std::vector::iterator it; @@ -461,6 +633,9 @@ int main() { TEST(vector::erase) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector; // set some values (from 1 to 10) @@ -481,6 +656,9 @@ int main() { TEST(vector::swap) { + // title + TITLE(cplusplus.com reference :) + std::vector foo (3,100); // three ints with a value of 100 std::vector bar (5,200); // five ints with a value of 200 @@ -500,6 +678,9 @@ int main() { TEST(vector::clear) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector; myvector.push_back (100); myvector.push_back (200); @@ -523,6 +704,9 @@ int main() { TEST(vector::get_allocator) { + // title + TITLE(cplusplus.com reference :) + std::vector myvector; int * p; unsigned int i; From 68ada8ca687eb562f32c4211d5b26c43bbc683a5 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 10 Jun 2022 11:21:19 +0200 Subject: [PATCH 18/53] first insert ok --- headers/vector.hpp | 34 +++++---- templates/vector.tpp | 128 ++++++++++++++++++++++++++++---- tests/main.cpp | 171 ++++++++++++++++++++++++++++++++++++------- 3 files changed, 277 insertions(+), 56 deletions(-) diff --git a/headers/vector.hpp b/headers/vector.hpp index 4816261..fbf715a 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -24,7 +24,7 @@ public: typedef T value_type; typedef Allocator allocator_type; typedef std::size_t size_type; -// typedef std::ptrdiff_t difference_type; + typedef std::ptrdiff_t difference_type; typedef T * iterator; typedef T const * const_iterator; @@ -62,16 +62,16 @@ public: *************/ // begin ------------------------------------- iterator begin(); - //const_iterator begin() const; + const_iterator begin() const; // end --------------------------------------- iterator end(); - //const_iterator end() const; + 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 : @@ -118,18 +118,24 @@ public: // pop_back ---------------------------------- void pop_back(); // insert ------------------------------------ - //iterator insert(iterator position, const value_type& val); - //void insert(iterator position, size_type n, const value_type& val); - //template - // void insert(iterator position, InputIterator first, InputIterator last); + iterator insert(iterator position, const value_type& val); +// void insert(iterator position, size_type n, const value_type& val); +// template +// void insert(iterator position, InputIterator first, InputIterator last); // erase ------------------------------------- - //iterator erase(iterator position); - //iterator erase(iterator first, iterator last); + iterator erase(iterator position); + iterator erase(iterator first, iterator last); // swap -------------------------------------- - //void swap(vector& x); + void swap(vector& x); // clear ------------------------------------- void clear(); + /************* + * allocator : + *************/ +// get_allocator ----------------------------- + allocator_type get_allocator() const; + private: diff --git a/templates/vector.tpp b/templates/vector.tpp index 03e030b..3cd1371 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -37,6 +37,7 @@ VT_TPL template VT:: assign(first, last); return; } +// copy constructor -------------------------- VT_TPL VT:: vector( vector const & src ) { @@ -50,15 +51,19 @@ VT_TPL VT:: VT_TPL VT & VT:: operator=( vector const & rhs ) { + vector new_vector; + //Base::operator=(rhs); if ( this != &rhs ) { - _size = rhs.size(); + new_vector.reserve(_capacity); + new_vector.assign(rhs.begin(), rhs.end()); + swap(new_vector); + //_size = rhs.size(); } return *this; } - /********************************************* * PUBLIC MEMBER FUNCTIONS *********************************************/ @@ -69,17 +74,23 @@ VT_TPL VT & VT:: // begin ------------------------------------- VT_TPL typename VT::iterator VT:: begin() { return _mem_ptr; } -//const_iterator begin() const; +VT_TPL typename VT::const_iterator VT:: + begin() const { return _mem_ptr; } // end --------------------------------------- VT_TPL typename VT::iterator VT:: end() { return &_mem_ptr[_size]; } -//const_iterator end() const; +VT_TPL typename VT::const_iterator VT:: + end() const { return &_mem_ptr[_size]; } // rbegin ------------------------------------ -//reverse_iterator rbegin(); -//const_reverse_iterator rbegin() const; +//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 -------------------------------------- -//reverse_iterator rend(); -//const_reverse_iterator rend() const; +//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 : @@ -234,21 +245,108 @@ VT_TPL void VT:: VT_TPL void VT:: pop_back() { _allocator.destroy(end() - 1); _size--; } // insert ------------------------------------ -//iterator insert(iterator position, const value_type& val); -//void insert(iterator position, size_type n, const value_type& val); -//template -// void insert(iterator position, InputIterator first, InputIterator last); +VT_TPL typename VT::iterator VT:: + insert(iterator position, const value_type& val) { + + difference_type distance; + iterator it; + + if (_size + 1 > _capacity) + { + distance = position - begin(); + _increment_capacity(1); + position = begin() + distance; + } + it = end(); + if (position != it) + { + _allocator.construct(it, *(it - 1)); + while (--it != position) + *(it + 1) = *it; + } + _allocator.destroy(position); + _allocator.construct(position, val); + _size++; + return (position); +} +//VT_TPL void VT:: +// insert(iterator position, size_type n, const value_type& val) { +// +//} +//VT_TPL template void VT:: +// insert(iterator position, InputIterator first, InputIterator last) { +// +//} // erase ------------------------------------- -//iterator erase(iterator position); -//iterator erase(iterator first, iterator last); +VT_TPL typename VT::iterator VT:: + erase(iterator position) { + + iterator i = position; + iterator it_end = end() - 1; + + while (i != it_end) + { + *i = *(i + 1); + ++i; + } + _allocator.destroy(it_end); + _size -= 1; + return (position); +} +VT_TPL typename VT::iterator VT:: + erase(iterator first, iterator last) { + + iterator it_end = end(); + difference_type diff = std::distance(first, last); + + if (diff <= 0) + return (first); + + it_end = end(); + while (last != it_end) + { + *first = *last; + first++; + last++; + } + _destroy(it_end - diff, it_end); + _size -= diff; + + return (first); +} // swap -------------------------------------- -//void swap(vector& x); +VT_TPL void VT:: + swap(vector& x) { + + T* tmp_mem_ptr; + size_type tmp_size; + size_type tmp_capacity; + + tmp_mem_ptr = x._mem_ptr; + tmp_size = x._size; + tmp_capacity = x._capacity; + + x._mem_ptr = _mem_ptr; + x._size = _size; + x._capacity = _capacity; + + _mem_ptr = tmp_mem_ptr; + _size = tmp_size; + _capacity = tmp_capacity; +} // clear ------------------------------------- VT_TPL void VT:: clear() { _destroy(begin(), end()); _size = 0; } +/************* + * allocator : + *************/ +// get_allocator ----------------------------- +VT_TPL typename VT::allocator_type VT:: + get_allocator() const { return (_allocator); } + /********************************************* * PRIVATE MEMBER FUNCTIONS diff --git a/tests/main.cpp b/tests/main.cpp index eb604ac..170a4bb 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -11,6 +11,8 @@ #include "vector.hpp" #endif +struct mystruct { int value; }; + int main() { /* @@ -42,14 +44,33 @@ int main() { // title TITLE(cplusplus.com reference :) - std::vector foo (3,0); - std::vector bar (5,0); + ft::vector foo (3,0); + ft::vector bar (5,0); bar = foo; - foo = std::vector(); + foo = ft::vector(); std::cout << "Size of foo: " << int(foo.size()) << '\n'; std::cout << "Size of bar: " << int(bar.size()) << '\n'; + + + // title + TITLE(more informations :) + + int size; + + size = foo.size(); + std::cout << "foo:\n"; + for (int i = 0; i < size; i++) + std::cout << "[" << i <<"]" << foo[i]; + std::cout << "\ncapacity: " << foo.capacity() << "\n"; + + size = bar.size(); + std::cout << "bar:\n"; + for (int i = 0; i < size; i++) + std::cout << "[" << i <<"]" << bar[i]; + std::cout << "\ncapacity: " << bar.capacity() << "\n"; + } TESTEND @@ -84,8 +105,10 @@ int main() { std::cout << '\n'; } TESTEND +*/ +/* TEST(vector::rbegin) { // title @@ -126,8 +149,10 @@ int main() { std::cout << '\n'; } TESTEND +*/ +/* TEST(vector::size) { // title @@ -153,7 +178,7 @@ int main() { // title TITLE(cplusplus.com reference :) - std::vector myvector; + ft::vector myvector; // set some content in the vector: for (int i=0; i<100; i++) myvector.push_back(i); @@ -163,7 +188,6 @@ int main() { std::cout << "max_size: " << myvector.max_size() << "\n"; } TESTEND -*/ TEST(vector::resize) @@ -599,44 +623,101 @@ int main() { std::cout << "capacity : " << myvector.capacity() << '\n'; } TESTEND +*/ -/* TEST(vector::insert) { +// // title +// TITLE(cplusplus.com reference :) +// +// std::vector myvector (3,100); +// std::vector::iterator it; +// +// it = myvector.begin(); +// it = myvector.insert ( it , 200 ); +// +// myvector.insert (it,2,300); +// +// // "it" no longer valid, get a new one: +// it = myvector.begin(); +// +// std::vector anothervector (2,400); +// myvector.insert (it+2,anothervector.begin(),anothervector.end()); +// +// int myarray [] = { 501,502,503 }; +// myvector.insert (myvector.begin(), myarray, myarray+3); +// +// std::cout << "myvector contains:"; +// for (it=myvector.begin(); it myvector (3,100); - std::vector::iterator it; - - it = myvector.begin(); - it = myvector.insert ( it , 200 ); - - myvector.insert (it,2,300); - - // "it" no longer valid, get a new one: - it = myvector.begin(); - - std::vector anothervector (2,400); - myvector.insert (it+2,anothervector.begin(),anothervector.end()); - - int myarray [] = { 501,502,503 }; - myvector.insert (myvector.begin(), myarray, myarray+3); + ft::vector myvector2 (3,100); + ft::vector::iterator it2; + it2 = myvector2.begin(); + std::cout << "\nsize:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; + myvector2.insert ( it2 , 200 ); std::cout << "myvector contains:"; - for (it=myvector.begin(); it myvector3 (3,100); + ft::vector::iterator it3; + + it3 = myvector3.end(); + std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; + myvector3.insert ( it3 , 200 ); + std::cout << "myvector contains:"; + for (it3 = myvector3.begin(); it3 < myvector3.end(); it3++) + std::cout << ' ' << *it3; + std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; + + + // title + TITLE(tests positions on insert(pos, value) with struct :) + + mystruct s_1; + mystruct s_2; + + s_1.value = 1; + s_2.value = 2; + + ft::vector myvector4 (3,s_1); + ft::vector::iterator it4; + + it4 = myvector4.begin(); + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + myvector4.insert ( it4 , s_2 ); + std::cout << "myvector contains:"; + for (it4 = myvector4.begin(); it4 < myvector4.end(); it4++) + std::cout << ' ' << (*it4).value; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + + it4 = myvector4.begin() + 2; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + myvector4.insert ( it4 , s_2 ); + std::cout << "myvector contains:"; + for (it4 = myvector4.begin(); it4 < myvector4.end(); it4++) + std::cout << ' ' << (*it4).value; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; } TESTEND + +/* TEST(vector::erase) { // title TITLE(cplusplus.com reference :) - std::vector myvector; + ft::vector myvector; // set some values (from 1 to 10) for (int i=1; i<=10; i++) myvector.push_back(i); @@ -651,9 +732,43 @@ int main() { for (unsigned i=0; i vector2; + int size; + + for (int i=1; i<=100; i++) vector2.push_back(i); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + + std::cout << "\nerase pos(7,36) :\n"; + vector2.erase(vector2.begin() + 7, vector2.begin() + 36); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + + std::cout << "\nerase pos(46,54) :\n"; + vector2.erase(vector2.begin() + 46, vector2.begin() + 54); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + + std::cout << "\nerase pos(7,7) :\n"; + vector2.erase(vector2.begin() + 7, vector2.begin() + 7); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; } TESTEND + TEST(vector::swap) { // title @@ -676,6 +791,7 @@ int main() { } TESTEND + TEST(vector::clear) { // title @@ -702,6 +818,7 @@ int main() { } TESTEND + TEST(vector::get_allocator) { // title From c187d34ce746e88d63270ee272cb205b12cc0476 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 10 Jun 2022 16:47:56 +0200 Subject: [PATCH 19/53] vector insert ok --- headers/vector.hpp | 7 +- templates/vector.tpp | 93 ++++++++++++++++--- tests/main.cpp | 207 +++++++++++++++++++++++++++++++------------ tests/test.sh | 6 +- 4 files changed, 240 insertions(+), 73 deletions(-) diff --git a/headers/vector.hpp b/headers/vector.hpp index fbf715a..5367d3b 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -119,9 +119,10 @@ public: void pop_back(); // insert ------------------------------------ iterator insert(iterator position, const value_type& val); -// void insert(iterator position, size_type n, const value_type& val); -// template -// void insert(iterator position, InputIterator first, InputIterator last); + void insert(iterator position, size_type n, const value_type& val); + template + typename enable_if< !is_integral::value,void >::type + insert(iterator position, InputIterator first, InputIterator last); // erase ------------------------------------- iterator erase(iterator position); iterator erase(iterator first, iterator last); diff --git a/templates/vector.tpp b/templates/vector.tpp index 3cd1371..3aa3c1a 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -259,9 +259,9 @@ VT_TPL typename VT::iterator VT:: } it = end(); if (position != it) - { + { _allocator.construct(it, *(it - 1)); - while (--it != position) + while (it-- != position) *(it + 1) = *it; } _allocator.destroy(position); @@ -269,14 +269,87 @@ VT_TPL typename VT::iterator VT:: _size++; return (position); } -//VT_TPL void VT:: -// insert(iterator position, size_type n, const value_type& val) { -// -//} -//VT_TPL template void VT:: -// insert(iterator position, InputIterator first, InputIterator last) { -// -//} +VT_TPL void VT:: + insert(iterator position, size_type n, const value_type& val) { + + difference_type distance; + iterator it_end; + iterator it; + + if (_size + n > _capacity) + { + distance = position - begin(); + _increment_capacity(n); + position = begin() + distance; + } + + it_end = end(); + if (position != it_end) + { + it = it_end; + while (it + n != it_end && it != position) + { + it--; + _allocator.construct(it + n, *it); + } + while (it != position) + { + it--; + *(it + n) = *it; + } + _destroy(position, std::min(position + n, it_end)); + } + + for (size_type i = 0; i < n; i++, position++) + _allocator.construct(position, val); + _size += n; +} +VT_TPL template +typename enable_if< !is_integral::value,void >::type VT:: + insert(iterator position, InputIterator first, InputIterator last) { + + difference_type dist; + difference_type n; + iterator it_end; + iterator it; + + n = std::distance(first, last); + if (_size + n > _capacity) + { + dist = position - begin(); + _increment_capacity(n); + position = begin() + dist; + } + + it_end = end(); + if (position != it_end) + { + it = it_end; + while (it + n != it_end && it != position) + { + it--; + _allocator.construct(it + n, *it); + } + while (it != position) + { + it--; + *(it + n) = *it; + } + _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); + ++position; + ++first; + } + + _size += n; +} // erase ------------------------------------- VT_TPL typename VT::iterator VT:: erase(iterator position) { diff --git a/tests/main.cpp b/tests/main.cpp index 170a4bb..23aca65 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -11,11 +11,23 @@ #include "vector.hpp" #endif -struct mystruct { int value; }; +/**/ // struct for tests +/**/ +/**/ struct mystruct { +/**/ public: +/**/ mystruct(int data = 1) {_val = new int[1]; _val[0] = data;} +/**/ ~mystruct() {delete[] _val;} +/**/ int * get_data() const {return _val;} +/**/ private: +/**/ int * _val; +/**/ }; +/**/ std::ostream & operator<<(std::ostream & o, mystruct const & rhs) { +/**/ o << rhs.get_data()[0]; +/**/ return (o); +/**/ } int main() { -/* TEST(vector::vector (constructor)) { // title @@ -105,7 +117,6 @@ int main() { std::cout << '\n'; } TESTEND -*/ /* @@ -152,7 +163,6 @@ int main() { */ -/* TEST(vector::size) { // title @@ -623,95 +633,177 @@ int main() { std::cout << "capacity : " << myvector.capacity() << '\n'; } TESTEND -*/ TEST(vector::insert) { -// // title -// TITLE(cplusplus.com reference :) -// -// std::vector myvector (3,100); -// std::vector::iterator it; -// -// it = myvector.begin(); -// it = myvector.insert ( it , 200 ); -// -// myvector.insert (it,2,300); -// -// // "it" no longer valid, get a new one: -// it = myvector.begin(); -// -// std::vector anothervector (2,400); -// myvector.insert (it+2,anothervector.begin(),anothervector.end()); -// -// int myarray [] = { 501,502,503 }; -// myvector.insert (myvector.begin(), myarray, myarray+3); -// -// std::cout << "myvector contains:"; -// for (it=myvector.begin(); it::iterator it; + ft::vector::iterator its; + int i; + + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (3,100); + + it = myvector.begin(); + it = myvector.insert ( it , 200 ); + myvector.insert (it,2,300); + + ft::vector anothervector (2,400); + it = myvector.begin(); + myvector.insert (it+2,anothervector.begin(),anothervector.end()); + + int myarray [] = { 501,502,503 }; + myvector.insert (myvector.begin(), myarray, myarray+3); + + std::cout << "myvector contains:"; + for (it=myvector.begin(); it myvector2 (3,100); - ft::vector::iterator it2; - it2 = myvector2.begin(); - std::cout << "\nsize:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; - myvector2.insert ( it2 , 200 ); + it = myvector2.begin(); + std::cout << "size:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; + myvector2.insert ( it , 200 ); std::cout << "myvector contains:"; - for (it2 = myvector2.begin(); it2 < myvector2.end(); it2++) - std::cout << ' ' << *it2; + for (it = myvector2.begin(); it < myvector2.end(); it++) + std::cout << ' ' << *it; std::cout << "\nsize:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; ft::vector myvector3 (3,100); - ft::vector::iterator it3; - it3 = myvector3.end(); + it = myvector3.end(); std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; - myvector3.insert ( it3 , 200 ); + myvector3.insert ( it , 200 ); std::cout << "myvector contains:"; - for (it3 = myvector3.begin(); it3 < myvector3.end(); it3++) - std::cout << ' ' << *it3; + for (it = myvector3.begin(); it < myvector3.end(); it++) + std::cout << ' ' << *it; std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; // title TITLE(tests positions on insert(pos, value) with struct :) - mystruct s_1; - mystruct s_2; + ft::vector myvector4; + mystruct *s; - s_1.value = 1; - s_2.value = 2; + i = 0; + while (i < 3) + { + s = new mystruct(i++); + myvector4.push_back(s); + } - ft::vector myvector4 (3,s_1); - ft::vector::iterator it4; - - it4 = myvector4.begin(); - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - myvector4.insert ( it4 , s_2 ); + its = myvector4.begin(); + std::cout << "size:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + s = new mystruct(i++); + myvector4.insert ( its , s ); std::cout << "myvector contains:"; - for (it4 = myvector4.begin(); it4 < myvector4.end(); it4++) - std::cout << ' ' << (*it4).value; + for (its = myvector4.begin(); its < myvector4.end(); its++) + std::cout << ' ' << **its; std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - it4 = myvector4.begin() + 2; + its = myvector4.begin() + 2; std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - myvector4.insert ( it4 , s_2 ); + s = new mystruct(i++); + myvector4.insert ( its , s ); std::cout << "myvector contains:"; - for (it4 = myvector4.begin(); it4 < myvector4.end(); it4++) - std::cout << ' ' << (*it4).value; + for (its = myvector4.begin(); its < myvector4.end(); its++) + std::cout << ' ' << **its; std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + + its = myvector4.end(); + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + s = new mystruct(i++); + myvector4.insert ( its , s ); + std::cout << "myvector contains:"; + for (its = myvector4.begin(); its < myvector4.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + + + // title + TITLE(tests insert(pos, size, value) :) + + ft::vector myvector5; + + for (i = 1; i <= 5; i++) + myvector5.push_back(i * 100); + + it = myvector5.begin() + 1; + myvector5.insert ( it , 150 ); + + it = myvector5.end(); + myvector5.insert (it,2,600); + + it = myvector5.end() - 2; + myvector5.insert (it,2,550); + + std::cout << "myvector contains:"; + for (it = myvector5.begin(); it < myvector5.end(); it++) + std::cout << ' ' << *it; + std::cout << '\n'; + std::cout << "\nsize:" << myvector5.size() << " capacity:" << myvector5.capacity() << "\n"; + + + // title + TITLE(tests positions on insert(pos, value) with struct :) + + ft::vector myvector6; + + i = 1; + while (i <= 5) + { + s = new mystruct(i++ * 100); + myvector6.push_back(s); + } + + its = myvector6.begin() + 1; + s = new mystruct(150); + myvector6.insert ( its , s ); + + its = myvector6.end(); + s = new mystruct(600); + myvector6.insert ( its, 2, s ); + + its = myvector6.end() - 2; + s = new mystruct(550); + myvector6.insert ( its, 2, s ); + + std::cout << "myvector contains:"; + for (its = myvector6.begin(); its < myvector6.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector6.size() << " capacity:" << myvector6.capacity() << "\n"; + + + // title + TITLE(tests insert(pos, first, last) with struct :) + + ft::vector myvector7; + + for (i = 0; i < 5; i++) + { + s = new mystruct(42); + myvector7.push_back(s); + } + + its = myvector7.begin() + 2; + myvector7.insert ( its, myvector6.begin() + 3, myvector6.end() - 2 ); + + std::cout << "myvector contains:"; + for (its = myvector7.begin(); its < myvector7.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector7.size() << " capacity:" << myvector7.capacity() << "\n"; } TESTEND -/* TEST(vector::erase) { // title @@ -843,7 +935,6 @@ int main() { myvector.get_allocator().deallocate(p,5); } TESTEND -*/ // execute tests and print them : diff --git a/tests/test.sh b/tests/test.sh index f180752..edbbfec 100644 --- a/tests/test.sh +++ b/tests/test.sh @@ -2,9 +2,11 @@ # cd $(dirname $0) make stl > /dev/null -./containers > tests/output_stl.log +echo -e "\nstl :" +time ./containers > tests/output_stl.log make ft > /dev/null -./containers > tests/output_ft.log +echo -e "\nft :" +time ./containers > tests/output_ft.log diff --context=0 --color=always tests/output_stl.log tests/output_ft.log From 988d67e90888cab9be8f7d4aaff920dac8667df8 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Mon, 13 Jun 2022 22:03:46 +0200 Subject: [PATCH 20/53] better test organisation --- Makefile | 13 +- headers/tests.hpp | 76 ++- tests/main.cpp | 1020 ++++----------------------------------- tests/tests_vectors.cpp | 970 +++++++++++++++++++++++++++++++++++++ 4 files changed, 1132 insertions(+), 947 deletions(-) create mode 100644 tests/tests_vectors.cpp diff --git a/Makefile b/Makefile index ccb02b8..85af6a4 100644 --- a/Makefile +++ b/Makefile @@ -49,8 +49,9 @@ INCLUDES = -I$(D_HEADERS) \ -I$(D_TEMPLATES) D_SRCS = ./tests -SRCS = main.cpp #SRCS = main42.cpp +SRCS = main.cpp \ + tests_vectors.cpp D_HEADERS = ./headers HEADERS = colors.h \ @@ -72,9 +73,9 @@ endif # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # -# . target: prerequisites . $@ : target # -# RULES . recipe . $< : 1st prerequisite # -# . recipe . $^ : all prerequisites # +# . target: prerequisites . $@ : target # +# RULES . recipe . $< : 1st prerequisite # +# . @recipe (silent) . $^ : all prerequisites # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # all: $(NAME) @@ -84,8 +85,8 @@ stl: re ft: re $(D_OBJS)/%.o: %.$(EXT) | $(D_OBJS) - @echo $(CYAN)"compilation (objects.o) :"$(RESET) - $(CC) $(CFLAGS) -c $< -o $@ + @echo $(CYAN)"compilation " $@ $(RESET) + @$(CC) $(CFLAGS) -c $< -o $@ $(D_OBJS): mkdir $@ diff --git a/headers/tests.hpp b/headers/tests.hpp index a5d2675..bb4d54b 100644 --- a/headers/tests.hpp +++ b/headers/tests.hpp @@ -1,16 +1,29 @@ -#ifndef TESTS_H -# define TESTS_H +#ifndef TESTS_HPP +# define TESTS_HPP +#include #include "colors.h" #include #include + +// ************************* +// toogle between test ft and stl +#include +#ifdef STL + namespace ft = std; +#else + #include "vector.hpp" +#endif + + +// *************************** +// adding each test to the list # define TEST(s) \ {\ test_title = #s;\ struct tester : public test_base {\ void func() - # define TESTEND \ };\ test = new(tester);\ @@ -18,15 +31,58 @@ test_list.push_back(test);\ } + +// ******************************* +// vector of functions test +struct test_base { std::string title; virtual void func(){} }; +extern std::vector test_list; +extern test_base *test; +extern std::string test_title; + + +// ************************************* +// defines for titles # define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; -struct test_base { - std::string title; - virtual void func() {} -}; -std::vector test_list; -test_base *test; -std::string test_title; +// *************************************** +// struct for tests +struct mystruct { +public: + mystruct(int data = 1) {_val = new int[1]; _val[0] = data;} + ~mystruct() {delete[] _val;} + int * get_data() const {return _val;} +private: + int * _val; +}; +extern std::ostream & operator<<(std::ostream & o, mystruct const & rhs); + + +// ********************************************* +// prototypes +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_size(); +void tests_vector_max_size(); +void tests_vector_resize(); +void tests_vector_capacity(); +void tests_vector_empty(); +void tests_vector_reserve(); +void tests_vector_operator_access(); +void tests_vector_at(); +void tests_vector_front(); +void tests_vector_back(); +void tests_vector_assign(); +void tests_vector_push_back(); +void tests_vector_pop_back(); +void tests_vector_insert(); +void tests_vector_erase(); +void tests_vector_swap(); +void tests_vector_clear(); +void tests_vector_get_allocator(); #endif diff --git a/tests/main.cpp b/tests/main.cpp index 23aca65..7a112ca 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,952 +1,110 @@ #include #include #include "colors.h" -#include "tests.hpp" #include // std::setw() +#include "tests.hpp" -#include -#ifdef STL - namespace ft = std; -#else - #include "vector.hpp" -#endif -/**/ // struct for tests -/**/ -/**/ struct mystruct { -/**/ public: -/**/ mystruct(int data = 1) {_val = new int[1]; _val[0] = data;} -/**/ ~mystruct() {delete[] _val;} -/**/ int * get_data() const {return _val;} -/**/ private: -/**/ int * _val; -/**/ }; -/**/ std::ostream & operator<<(std::ostream & o, mystruct const & rhs) { -/**/ o << rhs.get_data()[0]; -/**/ return (o); -/**/ } +// global declaration +std::ostream & operator<<(std::ostream & o, mystruct const & rhs) { + o << rhs.get_data()[0]; + return (o); +} +std::vector test_list; +test_base *test; +std::string test_title; + int main() { - TEST(vector::vector (constructor)) - { - // title - TITLE(cplusplus.com reference :) - - // constructors used in the same order as described above: - std::vector first; // empty vector of ints - std::vector second (4,100); // four ints with value 100 - std::vector third (second.begin(),second.end()); // iterating through second - std::vector fourth (third); // a copy of third - - // the iterator constructor can also be used to construct from arrays: - int myints[] = {16,2,77,29}; - std::vector fifth (myints, myints + sizeof(myints) / sizeof(int) ); - - std::cout << "The contents of fifth are:"; - for (std::vector::iterator it = fifth.begin(); it != fifth.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND - - - TEST(vector::=operator) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector foo (3,0); - ft::vector bar (5,0); - - bar = foo; - foo = ft::vector(); - - std::cout << "Size of foo: " << int(foo.size()) << '\n'; - std::cout << "Size of bar: " << int(bar.size()) << '\n'; - - - // title - TITLE(more informations :) - - int size; - - size = foo.size(); - std::cout << "foo:\n"; - for (int i = 0; i < size; i++) - std::cout << "[" << i <<"]" << foo[i]; - std::cout << "\ncapacity: " << foo.capacity() << "\n"; - - size = bar.size(); - std::cout << "bar:\n"; - for (int i = 0; i < size; i++) - std::cout << "[" << i <<"]" << bar[i]; - std::cout << "\ncapacity: " << bar.capacity() << "\n"; - - } - TESTEND - - - TEST(vector::begin) - { - // title - TITLE(cplusplus.com reference :) - - std::vector myvector; - for (int i=1; i<=5; i++) myvector.push_back(i); - - std::cout << "myvector contains:"; - for (std::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND - - - TEST(vector::end) - { - // title - TITLE(cplusplus.com reference :) - - std::vector myvector; - for (int i=1; i<=5; i++) myvector.push_back(i); - - std::cout << "myvector contains:"; - for (std::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND - - -/* - TEST(vector::rbegin) - { - // title - TITLE(cplusplus.com reference :) - - std::vector myvector (5); // 5 default-constructed ints - - int i=0; - - std::vector::reverse_iterator rit = myvector.rbegin(); - for (; rit!= myvector.rend(); ++rit) - *rit = ++i; - - std::cout << "myvector contains:"; - for (std::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND - - - TEST(vector::rend) - { - // title - TITLE(cplusplus.com reference :) - - std::vector myvector (5); // 5 default-constructed ints - - std::vector::reverse_iterator rit = myvector.rbegin(); - - int i=0; - for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit) - *rit = ++i; - - std::cout << "myvector contains:"; - for (std::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND -*/ - - - TEST(vector::size) - { - // title - TITLE(cplusplus.com reference :) - - std::vector myints; - std::cout << "0. size: " << myints.size() << '\n'; - - for (int i=0; i<10; i++) myints.push_back(i); - std::cout << "1. size: " << myints.size() << '\n'; - - myints.insert (myints.end(),10,100); - std::cout << "2. size: " << myints.size() << '\n'; - - myints.pop_back(); - std::cout << "3. size: " << myints.size() << '\n'; - } - TESTEND - - - TEST(vector::max_size) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - // set some content in the vector: - for (int i=0; i<100; i++) myvector.push_back(i); - - std::cout << "size: " << myvector.size() << "\n"; - std::cout << "capacity: " << myvector.capacity() << "\n"; - std::cout << "max_size: " << myvector.max_size() << "\n"; - } - TESTEND - - - TEST(vector::resize) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - // set some initial content: - for (int i = 1; i < 10; i++) myvector.push_back(i); - - myvector.resize(5); - myvector.resize(8,100); - myvector.resize(12); - - std::cout << "myvector contains:"; - for (unsigned int i = 0; i < myvector.size(); i++) - std::cout << ' ' << myvector[i]; - std::cout << '\n'; - - - // title - TITLE(test size and capacity 1 :) - - ft::vector vector2; - - std::cout << "size: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "assign(10, 1)\n"; - vector2.assign(10, 1); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(15)\n"; - vector2.resize(15); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(10)\n"; - vector2.resize(10); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(19)\n"; - vector2.resize(19); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(20)\n"; - vector2.resize(20); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(21)\n"; - vector2.resize(21); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - - // title - TITLE(test size and capacity 2 :) - - ft::vector vector3; - - std::cout << "size: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; - - std::cout << "assign(10, 1)\n"; - vector3.assign(10, 1); - for (unsigned int i = 0; i < vector3.size(); i++) - std::cout << "[" << i << "]" << vector3[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; - - std::cout << "resize(21)\n"; - vector3.resize(21); - for (unsigned int i = 0; i < vector3.size(); i++) - std::cout << "[" << i << "]" << vector3[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; - } - TESTEND - - - TEST(vector::capacity) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - // set some content in the vector: - for (int i=0; i<100; i++) myvector.push_back(i); - - std::cout << "size: " << (int) myvector.size() << '\n'; - std::cout << "capacity: " << (int) myvector.capacity() << '\n'; - std::cout << "max_size: " << (int) myvector.max_size() << '\n'; - } - TESTEND - - - TEST(vector::empty) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - int sum (0); - - for (int i=1;i<=10;i++) myvector.push_back(i); - - while (!myvector.empty()) - { - sum += myvector.back(); - myvector.pop_back(); - } - - std::cout << "total: " << sum << '\n'; - } - TESTEND - - - TEST(vector::reserve) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector::size_type sz; - ft::vector foo; - - sz = foo.capacity(); - std::cout << "making foo grow:\n"; - for (int i=0; i<100; ++i) { - foo.push_back(i); - if (sz!=foo.capacity()) { - sz = foo.capacity(); - std::cout << "capacity changed: " << sz << '\n'; - } - } - - ft::vector bar; - - sz = bar.capacity(); - bar.reserve(100); // this is the only difference with foo above - std::cout << "making bar grow:\n"; - for (int i=0; i<100; ++i) { - bar.push_back(i); - if (sz!=bar.capacity()) { - sz = bar.capacity(); - std::cout << "capacity changed: " << sz << '\n'; - } - } - } - TESTEND - - - TEST(vector::operator[]) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector (10); // 10 zero-initialized elements - ft::vector::size_type sz = myvector.size(); - - // assign some values: - for (unsigned i=0; i myvector (10); // 10 zero-initialized ints - - // assign some values: - for (unsigned i=0; i myvector; - - myvector.push_back(78); - myvector.push_back(16); - - // now front equals 78, and back 16 - - myvector.front() -= myvector.back(); - - std::cout << "myvector.front() is now " << myvector.front() << '\n'; - } - TESTEND - - - TEST(vector::back) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - myvector.push_back(78); - myvector.push_back(16); - - // now front equals 78, and back 16 - - myvector.front() -= myvector.back(); - std::cout << "myvector.front() is now " << myvector.front() << '\n'; - - - // title - TITLE(test with negatives :) - - myvector.push_back(236); - myvector.push_back(8973); - - myvector.front() -= myvector.back(); - std::cout << "myvector.front() is now " << myvector.front() << '\n'; - - - // title - TITLE(test with char :) - - ft::vector letters; - letters.push_back('o'); - letters.push_back('m'); - letters.push_back('g'); - letters.push_back('w'); - letters.push_back('t'); - letters.push_back('f'); - - if (!letters.empty()) { - std::cout << "The first character is '" << letters.front() << "'.\n"; - } - } - TESTEND - - TEST(vector::assign) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector first; - ft::vector second; - ft::vector third; - - first.assign (7,100); // 7 ints with a value of 100 - - ft::vector::iterator it; - it=first.begin()+1; - - second.assign (it,first.end()-1); // the 5 central values of first - - int myints[] = {1776,7,4}; - third.assign (myints,myints+3); // assigning from array. - - std::cout << "Size of first: " << int (first.size()) << '\n'; - std::cout << "Size of second: " << int (second.size()) << '\n'; - std::cout << "Size of third: " << int (third.size()) << '\n'; - - // title - TITLE(capacity tests of assignation :) - - ft::vector myvector; - int size; - - std::cout << "capacity before assignation : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 1\n"; - myvector.assign(1, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 3\n"; - myvector.assign(3, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 7268\n"; - myvector.assign(7268, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - - // title - TITLE(tests of iterators :) - - ft::vector int_vector_1; - ft::vector int_vector_2; - ft::vector int_vector_3; - ft::vector it_vector; - int ssize; - - std::cout << "\nassign 1\n"; - int_vector_1.assign(1, 12); - it_vector.assign(int_vector_1.begin(), int_vector_1.end()); - ssize = it_vector.size(); - for (int i = 0; i < ssize; i++) - std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - - std::cout << "\nassign 0\n"; - int_vector_2.assign(1, 6); - it_vector.assign(int_vector_2.begin(), int_vector_2.end() - 1); - ssize = it_vector.size(); - for (int i = 0; i < ssize; i++) - std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - - std::cout << "\nassign 266 - 13 - 172 = 81\n"; - int_vector_3.assign(266, 1); - it_vector.assign(int_vector_3.begin() + 13, int_vector_3.end() - 172); - ssize = it_vector.size(); - for (int i = 0; i < ssize; i++) - std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - } - TESTEND - - - TEST(vector::push_back) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; - int size = sizeof(myint) / sizeof(myint[0]); - for (int i = 0; i < size; i++) - { - myvector.push_back(myint[i]); - std::cout << "[capacity : " - << std::setw(2) << myvector.capacity() << "] " - << myvector[i] << "\n"; - } - for (int i = 0; i < size; i++) - std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; - std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; - - - // title - TITLE(big push back :) - - for (int i = 0; i < 72363; i++) - { - myvector.push_back(9); - std::cout << "[" << i - << ":" << myvector.capacity() << "] "; - } - std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; - } - TESTEND - - TEST(vector::pop_back) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - int sum (0); - - myvector.push_back (100); - myvector.push_back (200); - myvector.push_back (300); - - while (!myvector.empty()) - { - sum+=myvector.back(); - myvector.pop_back(); - } - - std::cout << "The elements of myvector add up to " << sum << '\n'; - - - // title - TITLE(check state :) - - std::cout << "size : " << myvector.size() << '\n'; - std::cout << "capacity : " << myvector.capacity() << '\n'; - } - TESTEND - - - TEST(vector::insert) - { - ft::vector::iterator it; - ft::vector::iterator its; - int i; - - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector (3,100); - - it = myvector.begin(); - it = myvector.insert ( it , 200 ); - myvector.insert (it,2,300); - - ft::vector anothervector (2,400); - it = myvector.begin(); - myvector.insert (it+2,anothervector.begin(),anothervector.end()); - - int myarray [] = { 501,502,503 }; - myvector.insert (myvector.begin(), myarray, myarray+3); - - std::cout << "myvector contains:"; - for (it=myvector.begin(); it myvector2 (3,100); - - it = myvector2.begin(); - std::cout << "size:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; - myvector2.insert ( it , 200 ); - std::cout << "myvector contains:"; - for (it = myvector2.begin(); it < myvector2.end(); it++) - std::cout << ' ' << *it; - std::cout << "\nsize:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; - - ft::vector myvector3 (3,100); - - it = myvector3.end(); - std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; - myvector3.insert ( it , 200 ); - std::cout << "myvector contains:"; - for (it = myvector3.begin(); it < myvector3.end(); it++) - std::cout << ' ' << *it; - std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; - - - // title - TITLE(tests positions on insert(pos, value) with struct :) - - ft::vector myvector4; - mystruct *s; - - i = 0; - while (i < 3) - { - s = new mystruct(i++); - myvector4.push_back(s); - } - - its = myvector4.begin(); - std::cout << "size:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - s = new mystruct(i++); - myvector4.insert ( its , s ); - std::cout << "myvector contains:"; - for (its = myvector4.begin(); its < myvector4.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - - its = myvector4.begin() + 2; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - s = new mystruct(i++); - myvector4.insert ( its , s ); - std::cout << "myvector contains:"; - for (its = myvector4.begin(); its < myvector4.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - - its = myvector4.end(); - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - s = new mystruct(i++); - myvector4.insert ( its , s ); - std::cout << "myvector contains:"; - for (its = myvector4.begin(); its < myvector4.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - - - // title - TITLE(tests insert(pos, size, value) :) - - ft::vector myvector5; - - for (i = 1; i <= 5; i++) - myvector5.push_back(i * 100); - - it = myvector5.begin() + 1; - myvector5.insert ( it , 150 ); - - it = myvector5.end(); - myvector5.insert (it,2,600); - - it = myvector5.end() - 2; - myvector5.insert (it,2,550); - - std::cout << "myvector contains:"; - for (it = myvector5.begin(); it < myvector5.end(); it++) - std::cout << ' ' << *it; - std::cout << '\n'; - std::cout << "\nsize:" << myvector5.size() << " capacity:" << myvector5.capacity() << "\n"; - - - // title - TITLE(tests positions on insert(pos, value) with struct :) - - ft::vector myvector6; - - i = 1; - while (i <= 5) - { - s = new mystruct(i++ * 100); - myvector6.push_back(s); - } - - its = myvector6.begin() + 1; - s = new mystruct(150); - myvector6.insert ( its , s ); - - its = myvector6.end(); - s = new mystruct(600); - myvector6.insert ( its, 2, s ); - - its = myvector6.end() - 2; - s = new mystruct(550); - myvector6.insert ( its, 2, s ); - - std::cout << "myvector contains:"; - for (its = myvector6.begin(); its < myvector6.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector6.size() << " capacity:" << myvector6.capacity() << "\n"; - - - // title - TITLE(tests insert(pos, first, last) with struct :) - - ft::vector myvector7; - - for (i = 0; i < 5; i++) - { - s = new mystruct(42); - myvector7.push_back(s); - } - - its = myvector7.begin() + 2; - myvector7.insert ( its, myvector6.begin() + 3, myvector6.end() - 2 ); - - std::cout << "myvector contains:"; - for (its = myvector7.begin(); its < myvector7.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector7.size() << " capacity:" << myvector7.capacity() << "\n"; - } - TESTEND - - - TEST(vector::erase) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - // set some values (from 1 to 10) - for (int i=1; i<=10; i++) myvector.push_back(i); - - // erase the 6th element - myvector.erase (myvector.begin()+5); - - // erase the first 3 elements: - myvector.erase (myvector.begin(),myvector.begin()+3); - - std::cout << "myvector contains:"; - for (unsigned i=0; i vector2; - int size; - - for (int i=1; i<=100; i++) vector2.push_back(i); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; - - std::cout << "\nerase pos(7,36) :\n"; - vector2.erase(vector2.begin() + 7, vector2.begin() + 36); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; - - std::cout << "\nerase pos(46,54) :\n"; - vector2.erase(vector2.begin() + 46, vector2.begin() + 54); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; - - std::cout << "\nerase pos(7,7) :\n"; - vector2.erase(vector2.begin() + 7, vector2.begin() + 7); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; - } - TESTEND - - - TEST(vector::swap) - { - // title - TITLE(cplusplus.com reference :) - - std::vector foo (3,100); // three ints with a value of 100 - std::vector bar (5,200); // five ints with a value of 200 - - foo.swap(bar); - - std::cout << "foo contains:"; - for (unsigned i=0; i myvector; - myvector.push_back (100); - myvector.push_back (200); - myvector.push_back (300); - - std::cout << "myvector contains:"; - for (unsigned i=0; i myvector; - int * p; - unsigned int i; - - // allocate an array with space for 5 elements using vector's allocator: - p = myvector.get_allocator().allocate(5); - - // construct values in-place on the array: - for (i=0; i<5; i++) myvector.get_allocator().construct(&p[i],i); - - std::cout << "The allocated array contains:"; - for (i=0; i<5; i++) std::cout << ' ' << p[i]; - std::cout << '\n'; - - // destroy and deallocate: - for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]); - myvector.get_allocator().deallocate(p,5); - } - TESTEND - + // VECTOR +// tests_vector_constructor(); + tests_vector_operator_assignation(); + tests_vector_begin(); + tests_vector_end(); +// tests_vector_rbegin(); +// tests_vector_rend(); + tests_vector_size(); + tests_vector_max_size(); + tests_vector_resize(); + tests_vector_capacity(); + tests_vector_empty(); + tests_vector_reserve(); + tests_vector_operator_access(); + tests_vector_at(); + tests_vector_front(); + tests_vector_back(); + tests_vector_assign(); + tests_vector_push_back(); + tests_vector_pop_back(); + tests_vector_insert(); + tests_vector_erase(); + tests_vector_swap(); + tests_vector_clear(); + tests_vector_get_allocator(); + + // MAP +// tests_map_constructor(); +// tests_map_operator_assignation(); +// tests_map_begin(); +// tests_map_end(); +// tests_map_rbegin(); +// tests_map_rend(); +// tests_map_size(); +// tests_map_max_size(); +// tests_map_resize(); +// tests_map_capacity(); +// tests_map_empty(); +// tests_map_reserve(); +// tests_map_operator_access(); +// tests_map_at(); +// tests_map_front(); +// tests_map_back(); +// tests_map_assign(); +// tests_map_push_back(); +// tests_map_pop_back(); +// tests_map_insert(); +// tests_map_erase(); +// tests_map_swap(); +// tests_map_clear(); +// tests_map_get_allocator(); + + // STACK +// tests_stack_constructor(); +// tests_stack_operator_assignation(); +// tests_stack_begin(); +// tests_stack_end(); +// tests_stack_rbegin(); +// tests_stack_rend(); +// tests_stack_size(); +// tests_stack_max_size(); +// tests_stack_resize(); +// tests_stack_capacity(); +// tests_stack_empty(); +// tests_stack_reserve(); +// tests_stack_operator_access(); +// tests_stack_at(); +// tests_stack_front(); +// tests_stack_back(); +// tests_stack_assign(); +// tests_stack_push_back(); +// tests_stack_pop_back(); +// tests_stack_insert(); +// tests_stack_erase(); +// tests_stack_swap(); +// tests_stack_clear(); +// tests_stack_get_allocator(); // execute tests and print them : - int size = test_list.size(); for(int i = 0; i < size; i++) { std::cout << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] " - << test_list[i]->title << " :" RESET "\n"; + << test_list[i]->title << RESET "\n"; test_list[i]->func(); } + std::cout << "\n"; return 0; } diff --git a/tests/tests_vectors.cpp b/tests/tests_vectors.cpp new file mode 100644 index 0000000..6fb561f --- /dev/null +++ b/tests/tests_vectors.cpp @@ -0,0 +1,970 @@ +#ifndef TESTS_VECTORS_CPP +#define TESTS_VECTORS_CPP + +#include +#include +//#include "colors.h" +#include "tests.hpp" +#include // std::setw() + + +void tests_vector_constructor() +{ + TEST(vector::vector (constructor)) + { + // title + TITLE(cplusplus.com reference) + + // constructors used in the same order as described above: + ft::vector first; // empty vector of ints + ft::vector second (4,100); // four ints with value 100 + ft::vector third (second.begin(),second.end()); // iterating through second + ft::vector fourth (third); // a copy of third + + // the iterator constructor can also be used to construct from arrays: + int myints[] = {16,2,77,29}; + ft::vector fifth (myints, myints + sizeof(myints) / sizeof(int) ); + + std::cout << "The contents of fifth are:"; + for (ft::vector::iterator it = fifth.begin(); it != fifth.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + TESTEND +} + +void tests_vector_operator_assignation() +{ + TEST(vector::=operator) + { + // title + TITLE(cplusplus.com reference) + + ft::vector foo (3,0); + ft::vector bar (5,0); + + bar = foo; + foo = ft::vector(); + + std::cout << "Size of foo: " << int(foo.size()) << '\n'; + std::cout << "Size of bar: " << int(bar.size()) << '\n'; + + + // title + TITLE(more informations) + + int size; + + size = foo.size(); + std::cout << "foo:\n"; + for (int i = 0; i < size; i++) + std::cout << "[" << i <<"]" << foo[i]; + std::cout << "\ncapacity: " << foo.capacity() << "\n"; + + size = bar.size(); + std::cout << "bar:\n"; + for (int i = 0; i < size; i++) + std::cout << "[" << i <<"]" << bar[i]; + std::cout << "\ncapacity: " << bar.capacity() << "\n"; + + } + TESTEND +} + +void tests_vector_begin() { + TEST(vector::begin) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + for (int i=1; i<=5; i++) myvector.push_back(i); + + std::cout << "myvector contains:"; + for (ft::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + TESTEND +} + +void tests_vector_end() +{ + TEST(vector::end) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + for (int i=1; i<=5; i++) myvector.push_back(i); + + std::cout << "myvector contains:"; + for (ft::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + TESTEND +} + +/* +void tests_vector_rbegin() +{ + TEST(vector::rbegin) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (5); // 5 default-constructed ints + + int i=0; + + ft::vector::reverse_iterator rit = myvector.rbegin(); + for (; rit!= myvector.rend(); ++rit) + *rit = ++i; + + std::cout << "myvector contains:"; + for (ft::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + TESTEND +} + +void tests_vector_rend() +{ + TEST(vector::rend) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (5); // 5 default-constructed ints + + ft::vector::reverse_iterator rit = myvector.rbegin(); + + int i=0; + for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit) + *rit = ++i; + + std::cout << "myvector contains:"; + for (ft::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; + } + TESTEND +} +*/ + + +void tests_vector_size() +{ + TEST(vector::size) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myints; + std::cout << "0. size: " << myints.size() << '\n'; + + for (int i=0; i<10; i++) myints.push_back(i); + std::cout << "1. size: " << myints.size() << '\n'; + + myints.insert (myints.end(),10,100); + std::cout << "2. size: " << myints.size() << '\n'; + + myints.pop_back(); + std::cout << "3. size: " << myints.size() << '\n'; + } + TESTEND +} + +void tests_vector_max_size() +{ + TEST(vector::max_size) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + // set some content in the vector: + for (int i=0; i<100; i++) myvector.push_back(i); + + std::cout << "size: " << myvector.size() << "\n"; + std::cout << "capacity: " << myvector.capacity() << "\n"; + std::cout << "max_size: " << myvector.max_size() << "\n"; + } + TESTEND +} + +void tests_vector_resize() +{ + TEST(vector::resize) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + // set some initial content: + for (int i = 1; i < 10; i++) myvector.push_back(i); + + myvector.resize(5); + myvector.resize(8,100); + myvector.resize(12); + + std::cout << "myvector contains:"; + for (unsigned int i = 0; i < myvector.size(); i++) + std::cout << ' ' << myvector[i]; + std::cout << '\n'; + + + // title + TITLE(test size and capacity 1 :) + + ft::vector vector2; + + std::cout << "size: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "assign(10, 1)\n"; + vector2.assign(10, 1); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(15)\n"; + vector2.resize(15); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(10)\n"; + vector2.resize(10); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(19)\n"; + vector2.resize(19); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(20)\n"; + vector2.resize(20); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "resize(21)\n"; + vector2.resize(21); + for (unsigned int i = 0; i < vector2.size(); i++) + std::cout << "[" << i << "]" << vector2[i] << " "; + std::cout << "\n"; + + + // title + TITLE(test size and capacity 2 :) + + ft::vector vector3; + + std::cout << "size: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; + + std::cout << "assign(10, 1)\n"; + vector3.assign(10, 1); + for (unsigned int i = 0; i < vector3.size(); i++) + std::cout << "[" << i << "]" << vector3[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; + + std::cout << "resize(21)\n"; + vector3.resize(21); + for (unsigned int i = 0; i < vector3.size(); i++) + std::cout << "[" << i << "]" << vector3[i] << " "; + std::cout << "\n"; + + std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; + } + TESTEND +} + +void tests_vector_capacity() +{ + TEST(vector::capacity) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + // set some content in the vector: + for (int i=0; i<100; i++) myvector.push_back(i); + + std::cout << "size: " << (int) myvector.size() << '\n'; + std::cout << "capacity: " << (int) myvector.capacity() << '\n'; + std::cout << "max_size: " << (int) myvector.max_size() << '\n'; + } + TESTEND +} + +void tests_vector_empty() +{ + TEST(vector::empty) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + int sum (0); + + for (int i=1;i<=10;i++) myvector.push_back(i); + + while (!myvector.empty()) + { + sum += myvector.back(); + myvector.pop_back(); + } + + std::cout << "total: " << sum << '\n'; + } + TESTEND +} + +void tests_vector_reserve() +{ + TEST(vector::reserve) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector::size_type sz; + ft::vector foo; + + sz = foo.capacity(); + std::cout << "making foo grow:\n"; + for (int i=0; i<100; ++i) { + foo.push_back(i); + if (sz!=foo.capacity()) { + sz = foo.capacity(); + std::cout << "capacity changed: " << sz << '\n'; + } + } + + ft::vector bar; + + sz = bar.capacity(); + bar.reserve(100); // this is the only difference with foo above + std::cout << "making bar grow:\n"; + for (int i=0; i<100; ++i) { + bar.push_back(i); + if (sz!=bar.capacity()) { + sz = bar.capacity(); + std::cout << "capacity changed: " << sz << '\n'; + } + } + } + TESTEND +} + +void tests_vector_operator_access() +{ + TEST(vector::operator[]) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (10); // 10 zero-initialized elements + ft::vector::size_type sz = myvector.size(); + + // assign some values: + for (unsigned i=0; i myvector (10); // 10 zero-initialized ints + + // assign some values: + for (unsigned i=0; i myvector; + + myvector.push_back(78); + myvector.push_back(16); + + // now front equals 78, and back 16 + + myvector.front() -= myvector.back(); + + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + } + TESTEND +} + +void tests_vector_back() +{ + TEST(vector::back) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + myvector.push_back(78); + myvector.push_back(16); + + // now front equals 78, and back 16 + + myvector.front() -= myvector.back(); + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + + + // title + TITLE(test with negatives :) + + myvector.push_back(236); + myvector.push_back(8973); + + myvector.front() -= myvector.back(); + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + + + // title + TITLE(test with char :) + + ft::vector letters; + letters.push_back('o'); + letters.push_back('m'); + letters.push_back('g'); + letters.push_back('w'); + letters.push_back('t'); + letters.push_back('f'); + + if (!letters.empty()) { + std::cout << "The first character is '" << letters.front() << "'.\n"; + } + } + TESTEND +} + +void tests_vector_assign() +{ + TEST(vector::assign) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector first; + ft::vector second; + ft::vector third; + + first.assign (7,100); // 7 ints with a value of 100 + + ft::vector::iterator it; + it=first.begin()+1; + + second.assign (it,first.end()-1); // the 5 central values of first + + int myints[] = {1776,7,4}; + third.assign (myints,myints+3); // assigning from array. + + std::cout << "Size of first: " << int (first.size()) << '\n'; + std::cout << "Size of second: " << int (second.size()) << '\n'; + std::cout << "Size of third: " << int (third.size()) << '\n'; + + // title + TITLE(capacity tests of assignation :) + + ft::vector myvector; + int size; + + std::cout << "capacity before assignation : " << myvector.capacity() << "\n"; + + std::cout << "\nassign 1\n"; + myvector.assign(1, 12); + size = myvector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << myvector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; + + std::cout << "\nassign 3\n"; + myvector.assign(3, 12); + size = myvector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << myvector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; + + std::cout << "\nassign 7268\n"; + myvector.assign(7268, 12); + size = myvector.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << myvector[i] << " - "; + std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; + + + // title + TITLE(tests of iterators :) + + ft::vector int_vector_1; + ft::vector int_vector_2; + ft::vector int_vector_3; + ft::vector it_vector; + int ssize; + + std::cout << "\nassign 1\n"; + int_vector_1.assign(1, 12); + it_vector.assign(int_vector_1.begin(), int_vector_1.end()); + ssize = it_vector.size(); + for (int i = 0; i < ssize; i++) + std::cout << "[" << i << "] " << it_vector[i] << " - "; + std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; + + std::cout << "\nassign 0\n"; + int_vector_2.assign(1, 6); + it_vector.assign(int_vector_2.begin(), int_vector_2.end() - 1); + ssize = it_vector.size(); + for (int i = 0; i < ssize; i++) + std::cout << "[" << i << "] " << it_vector[i] << " - "; + std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; + + std::cout << "\nassign 266 - 13 - 172 = 81\n"; + int_vector_3.assign(266, 1); + it_vector.assign(int_vector_3.begin() + 13, int_vector_3.end() - 172); + ssize = it_vector.size(); + for (int i = 0; i < ssize; i++) + std::cout << "[" << i << "] " << it_vector[i] << " - "; + std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; + } + TESTEND +} + +void tests_vector_push_back() +{ + TEST(vector::push_back) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; + int size = sizeof(myint) / sizeof(myint[0]); + for (int i = 0; i < size; i++) + { + myvector.push_back(myint[i]); + std::cout << "[capacity : " + << std::setw(2) << myvector.capacity() << "] " + << myvector[i] << "\n"; + } + for (int i = 0; i < size; i++) + std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; + std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; + + + // title + TITLE(big push back :) + + for (int i = 0; i < 72363; i++) + { + myvector.push_back(9); + std::cout << "[" << i + << ":" << myvector.capacity() << "] "; + } + std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; + } + TESTEND +} + +void tests_vector_pop_back() +{ + TEST(vector::pop_back) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + int sum (0); + + myvector.push_back (100); + myvector.push_back (200); + myvector.push_back (300); + + while (!myvector.empty()) + { + sum+=myvector.back(); + myvector.pop_back(); + } + + std::cout << "The elements of myvector add up to " << sum << '\n'; + + + // title + TITLE(check state :) + + std::cout << "size : " << myvector.size() << '\n'; + std::cout << "capacity : " << myvector.capacity() << '\n'; + } + TESTEND +} + +void tests_vector_insert() +{ + TEST(vector::insert) + { + ft::vector::iterator it; + ft::vector::iterator its; + int i; + + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (3,100); + + it = myvector.begin(); + it = myvector.insert ( it , 200 ); + myvector.insert (it,2,300); + + ft::vector anothervector (2,400); + it = myvector.begin(); + myvector.insert (it+2,anothervector.begin(),anothervector.end()); + + int myarray [] = { 501,502,503 }; + myvector.insert (myvector.begin(), myarray, myarray+3); + + std::cout << "myvector contains:"; + for (it=myvector.begin(); it myvector2 (3,100); + + it = myvector2.begin(); + std::cout << "size:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; + myvector2.insert ( it , 200 ); + std::cout << "myvector contains:"; + for (it = myvector2.begin(); it < myvector2.end(); it++) + std::cout << ' ' << *it; + std::cout << "\nsize:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; + + ft::vector myvector3 (3,100); + + it = myvector3.end(); + std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; + myvector3.insert ( it , 200 ); + std::cout << "myvector contains:"; + for (it = myvector3.begin(); it < myvector3.end(); it++) + std::cout << ' ' << *it; + std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; + + + // title + TITLE(tests positions on insert(pos, value) with struct :) + + ft::vector myvector4; + mystruct *s; + + i = 0; + while (i < 3) + { + s = new mystruct(i++); + myvector4.push_back(s); + } + + its = myvector4.begin(); + std::cout << "size:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + s = new mystruct(i++); + myvector4.insert ( its , s ); + std::cout << "myvector contains:"; + for (its = myvector4.begin(); its < myvector4.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + + its = myvector4.begin() + 2; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + s = new mystruct(i++); + myvector4.insert ( its , s ); + std::cout << "myvector contains:"; + for (its = myvector4.begin(); its < myvector4.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + + its = myvector4.end(); + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + s = new mystruct(i++); + myvector4.insert ( its , s ); + std::cout << "myvector contains:"; + for (its = myvector4.begin(); its < myvector4.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; + + + // title + TITLE(tests insert(pos, size, value) :) + + ft::vector myvector5; + + for (i = 1; i <= 5; i++) + myvector5.push_back(i * 100); + + it = myvector5.begin() + 1; + myvector5.insert ( it , 150 ); + + it = myvector5.end(); + myvector5.insert (it,2,600); + + it = myvector5.end() - 2; + myvector5.insert (it,2,550); + + std::cout << "myvector contains:"; + for (it = myvector5.begin(); it < myvector5.end(); it++) + std::cout << ' ' << *it; + std::cout << '\n'; + std::cout << "\nsize:" << myvector5.size() << " capacity:" << myvector5.capacity() << "\n"; + + + // title + TITLE(tests positions on insert(pos, value) with struct :) + + ft::vector myvector6; + + i = 1; + while (i <= 5) + { + s = new mystruct(i++ * 100); + myvector6.push_back(s); + } + + its = myvector6.begin() + 1; + s = new mystruct(150); + myvector6.insert ( its , s ); + + its = myvector6.end(); + s = new mystruct(600); + myvector6.insert ( its, 2, s ); + + its = myvector6.end() - 2; + s = new mystruct(550); + myvector6.insert ( its, 2, s ); + + std::cout << "myvector contains:"; + for (its = myvector6.begin(); its < myvector6.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector6.size() << " capacity:" << myvector6.capacity() << "\n"; + + + // title + TITLE(tests insert(pos, first, last) with struct :) + + ft::vector myvector7; + + for (i = 0; i < 5; i++) + { + s = new mystruct(42); + myvector7.push_back(s); + } + + its = myvector7.begin() + 2; + myvector7.insert ( its, myvector6.begin() + 3, myvector6.end() - 2 ); + + std::cout << "myvector contains:"; + for (its = myvector7.begin(); its < myvector7.end(); its++) + std::cout << ' ' << **its; + std::cout << "\nsize:" << myvector7.size() << " capacity:" << myvector7.capacity() << "\n"; + } + TESTEND +} + +void tests_vector_erase() +{ + TEST(vector::erase) + { + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + // set some values (from 1 to 10) + for (int i=1; i<=10; i++) myvector.push_back(i); + + // erase the 6th element + myvector.erase (myvector.begin()+5); + + // erase the first 3 elements: + myvector.erase (myvector.begin(),myvector.begin()+3); + + std::cout << "myvector contains:"; + for (unsigned i=0; i vector2; + int size; + + for (int i=1; i<=100; i++) vector2.push_back(i); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + + std::cout << "\nerase pos(7,36) :\n"; + vector2.erase(vector2.begin() + 7, vector2.begin() + 36); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + + std::cout << "\nerase pos(46,54) :\n"; + vector2.erase(vector2.begin() + 46, vector2.begin() + 54); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + + std::cout << "\nerase pos(7,7) :\n"; + vector2.erase(vector2.begin() + 7, vector2.begin() + 7); + size = vector2.size(); + for (int i = 0; i < size; i++) + std::cout << "[" << i << "] " << vector2[i] << " "; + std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + } + TESTEND +} + +void tests_vector_swap() +{ + TEST(vector::swap) + { + // 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 (unsigned i=0; i myvector; + myvector.push_back (100); + myvector.push_back (200); + myvector.push_back (300); + + std::cout << "myvector contains:"; + for (unsigned i=0; i myvector; + int * p; + unsigned int i; + + // allocate an array with space for 5 elements using vector's allocator: + p = myvector.get_allocator().allocate(5); + + // construct values in-place on the array: + for (i=0; i<5; i++) myvector.get_allocator().construct(&p[i],i); + + std::cout << "The allocated array contains:"; + for (i=0; i<5; i++) std::cout << ' ' << p[i]; + std::cout << '\n'; + + // destroy and deallocate: + for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]); + myvector.get_allocator().deallocate(p,5); + } + TESTEND +} + +#endif From 005382a3ac1bb5e3d8b8b25a32c61e198952b94f Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 14 Jun 2022 21:25:16 +0200 Subject: [PATCH 21/53] vector finish --- Makefile | 6 + headers/equal.hpp | 36 ++++++ headers/iterator_traits.hpp | 44 +++++++ headers/lexicographical_compare.hpp | 42 +++++++ headers/reverse_iterator.hpp | 140 +++++++++++++++++++++ headers/tests.hpp | 15 ++- headers/vector.hpp | 55 +++++++-- templates/vector.tpp | 112 ++++++++++------- tests/main.cpp | 9 +- tests/test.sh | 12 +- tests/tests_vectors.cpp | 184 ++++++++++++++++++++++++++-- 11 files changed, 584 insertions(+), 71 deletions(-) create mode 100644 headers/equal.hpp create mode 100644 headers/iterator_traits.hpp create mode 100644 headers/lexicographical_compare.hpp create mode 100644 headers/reverse_iterator.hpp 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 From bb4ac9963dc5a92d94ae90f88a550b2d35381786 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 15 Jun 2022 19:33:39 +0200 Subject: [PATCH 22/53] tests multi types --- Makefile | 3 +- headers/tests.hpp | 95 ------------------------------------- headers/tests_proto.hpp | 49 +++++++++++++++++++ headers/tests_utils.hpp | 101 ++++++++++++++++++++++++++++++++++++++++ tests/main.cpp | 70 ++++++++++++---------------- tests/tests_vectors.cpp | 18 ++++++- 6 files changed, 200 insertions(+), 136 deletions(-) delete mode 100644 headers/tests.hpp create mode 100644 headers/tests_proto.hpp create mode 100644 headers/tests_utils.hpp diff --git a/Makefile b/Makefile index c306260..9b8a52f 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,8 @@ SRCS = main.cpp \ D_HEADERS = ./headers HEADERS = colors.h \ - tests.hpp \ + tests_utils.hpp \ + tests_proto.hpp \ \ enable_if.hpp \ iterator_traits.hpp \ diff --git a/headers/tests.hpp b/headers/tests.hpp deleted file mode 100644 index f8291bf..0000000 --- a/headers/tests.hpp +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef TESTS_HPP -# define TESTS_HPP - -#include -#include -#include "colors.h" -#include -#include // std::setw() -#include // std::reverse_iterator -#include // std::make_pair -#include // std::map - - -// ************************* -// toogle between test ft and stl -#ifdef STL - namespace ft = std; -#else - #include "vector.hpp" - #include "reverse_iterator.hpp" -#endif - - -// *************************** -// adding each test to the list -# define TEST(s) \ - {\ - test_title = #s;\ - struct tester : public test_base {\ - void func() -# define TESTEND \ - };\ - test = new(tester);\ - test->title = test_title;\ - test_list.push_back(test);\ - } - - -// ******************************* -// vector of functions test -struct test_base { std::string title; virtual void func(){} }; -extern std::vector test_list; -extern test_base *test; -extern std::string test_title; - - -// ************************************* -// defines for titles -# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; - - -// *************************************** -// struct for tests -struct mystruct { -public: - mystruct(int data = 1) {_val = new int[1]; _val[0] = data;} - ~mystruct() {delete[] _val;} - int * get_data() const {return _val;} -private: - int * _val; -}; -extern std::ostream & operator<<(std::ostream & o, mystruct const & rhs); - - -// ********************************************* -// prototypes -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_size(); -void tests_vector_max_size(); -void tests_vector_resize(); -void tests_vector_capacity(); -void tests_vector_empty(); -void tests_vector_reserve(); -void tests_vector_operator_access(); -void tests_vector_at(); -void tests_vector_front(); -void tests_vector_back(); -void tests_vector_assign(); -void tests_vector_push_back(); -void tests_vector_pop_back(); -void tests_vector_insert(); -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/tests_proto.hpp b/headers/tests_proto.hpp new file mode 100644 index 0000000..d6e0671 --- /dev/null +++ b/headers/tests_proto.hpp @@ -0,0 +1,49 @@ +#ifndef TESTS_PROTO_HPP +# define TESTS_PROTO_HPP + +#include + +// ************************************ +// global declarations +struct A_test { virtual void func() = 0; }; +std::vector test_list; +void add_to_list(A_test * s1, A_test * s2, A_test * s3, A_test * s4) + { test_list.push_back(s1) + ; test_list.push_back(s2) + ; test_list.push_back(s3) + ; test_list.push_back(s4); } + + +// ********************************************* +// prototypes +void test_simple(); +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_size(); +void tests_vector_max_size(); +void tests_vector_resize(); +void tests_vector_capacity(); +void tests_vector_empty(); +void tests_vector_reserve(); +void tests_vector_operator_access(); +void tests_vector_at(); +void tests_vector_front(); +void tests_vector_back(); +void tests_vector_assign(); +void tests_vector_push_back(); +void tests_vector_pop_back(); +void tests_vector_insert(); +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/tests_utils.hpp b/headers/tests_utils.hpp new file mode 100644 index 0000000..d0053b6 --- /dev/null +++ b/headers/tests_utils.hpp @@ -0,0 +1,101 @@ +#ifndef TESTS_UTILS_HPP +# define TESTS_UTILS_HPP + +#include "colors.h" +#include +#include +#include +#include // std::setw() +#include // std::reverse_iterator +#include // std::make_pair +#include // std::map +#include + + +// toogle between test ft and stl +// ************************* +#ifdef STL + namespace ft = std; +#else + #include "vector.hpp" + #include "reverse_iterator.hpp" +#endif + + +// global declarations +// ************************************ +struct A_test { virtual void func() = 0; }; +extern std::vector test_list; +extern void add_to_list(A_test * s1, A_test * s2, A_test * s3, A_test * s4); + + +// struct for tests +// *************************************** +struct mystruct { +public: + mystruct(int data = 0) {_val = new int[5]; _val[0] = data;} + ~mystruct() {delete[] _val;} + int * get_data() const {return _val;} +private: + int * _val; +}; +//extern std::ostream & operator<<(std::ostream & o, mystruct const & rhs); +std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { + o << (*rhs).get_data()[0]; + return (o); +} + + +// adding each test to the list +// *************************** +#define TEST(f_name) \ + template struct s_ ## f_name : public A_test\ + { void func(); };\ + void f_name ()\ + { add_to_list(\ + new(s_ ## f_name )\ + ,new(s_ ## f_name )\ + ,new(s_ ## f_name )\ + ,new(s_ ## f_name )\ + );}\ + template \ + void s_ ## f_name ::func() + + +// defines +// **************************************** +# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; +# define VAL(n) ito(n) + + +// get a value +// ********************************************* +// generic +template + T ito(int n) {(void)n; return (T()); +} +template <> + int ito(int n) {return (n); +} +template <> + char ito(int n) {return (n % 94 + 33); +} +template <> + std::string ito(int n) { + + std::string str; + std::stringstream stream; + + stream << n; + stream >> str; + stream.clear(); + return (str); +} +template <> + mystruct* ito(int n) { + + return ( new mystruct(n) ); +} + + +#endif diff --git a/tests/main.cpp b/tests/main.cpp index 074d8df..5679086 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -2,49 +2,40 @@ #include #include "colors.h" #include // std::setw() -#include "tests.hpp" - - -// global declaration -std::ostream & operator<<(std::ostream & o, mystruct const & rhs) { - o << rhs.get_data()[0]; - return (o); -} -std::vector test_list; -test_base *test; -std::string test_title; +#include "tests_proto.hpp" int main() { // VECTOR - tests_vector_constructor(); - tests_vector_operator_assignation(); - tests_vector_begin(); - tests_vector_end(); - tests_vector_rbegin(); - tests_vector_rend(); - tests_vector_size(); - tests_vector_max_size(); - tests_vector_resize(); - tests_vector_capacity(); - tests_vector_empty(); - tests_vector_reserve(); - tests_vector_operator_access(); - tests_vector_at(); - tests_vector_front(); - tests_vector_back(); - tests_vector_assign(); - tests_vector_push_back(); - tests_vector_pop_back(); - tests_vector_insert(); - tests_vector_erase(); - tests_vector_swap(); - tests_vector_clear(); - tests_vector_get_allocator(); - tests_vector_relational_operators(); - tests_vector_swap_non_member(); - tests_vector_reverse_iterators(); + test_simple(); +// tests_vector_constructor(); +// tests_vector_operator_assignation(); +// tests_vector_begin(); +// tests_vector_end(); +// tests_vector_rbegin(); +// tests_vector_rend(); +// tests_vector_size(); +// tests_vector_max_size(); +// tests_vector_resize(); +// tests_vector_capacity(); +// tests_vector_empty(); +// tests_vector_reserve(); +// tests_vector_operator_access(); +// tests_vector_at(); +// tests_vector_front(); +// tests_vector_back(); +// tests_vector_assign(); +// tests_vector_push_back(); +// tests_vector_pop_back(); +// tests_vector_insert(); +// tests_vector_erase(); +// 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(); @@ -104,7 +95,8 @@ int main() { { std::cout << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] " - << test_list[i]->title << RESET "\n"; +// << test_list[i]->title << RESET "\n"; + << RESET "\n"; test_list[i]->func(); } std::cout << "\n"; diff --git a/tests/tests_vectors.cpp b/tests/tests_vectors.cpp index 89d4c99..e5b1a48 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vectors.cpp @@ -1,9 +1,24 @@ #ifndef TESTS_VECTORS_CPP #define TESTS_VECTORS_CPP -#include "tests.hpp" +#include "tests_utils.hpp" +//TEST2(test_simple(), "test") +TEST(test_simple) +{ + // title + TITLE(cplusplus.com reference) + T myints[] = {VAL(16),VAL(2),VAL(77),VAL(29)}; + ft::vector myvector (myints, myints + sizeof(myints) / sizeof(T) ); + + for (typename ft::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) + std::cout << ' ' << *it; + std::cout << '\n'; +} +//TEST2END + +/* void tests_vector_constructor() { TEST(vector::vector (constructor)) @@ -1136,5 +1151,6 @@ void tests_vector_reverse_iterators() } TESTEND } +*/ #endif From 32c413f74145cd41e3e0593944bb610c76e802e0 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 15 Jun 2022 21:04:31 +0200 Subject: [PATCH 23/53] add type in tests --- Makefile | 1 + headers/A_test.hpp | 14 ++++++++++++++ headers/tests_proto.hpp | 27 ++++++++++++++++++++------- headers/tests_utils.hpp | 38 +++++++++++++++++++------------------- tests/main.cpp | 17 +++++++++++------ 5 files changed, 65 insertions(+), 32 deletions(-) create mode 100644 headers/A_test.hpp diff --git a/Makefile b/Makefile index 9b8a52f..c1ae16b 100644 --- a/Makefile +++ b/Makefile @@ -57,6 +57,7 @@ D_HEADERS = ./headers HEADERS = colors.h \ tests_utils.hpp \ tests_proto.hpp \ + A_test.hpp \ \ enable_if.hpp \ iterator_traits.hpp \ diff --git a/headers/A_test.hpp b/headers/A_test.hpp new file mode 100644 index 0000000..1f4c86b --- /dev/null +++ b/headers/A_test.hpp @@ -0,0 +1,14 @@ +#ifndef A_TEST_HPP +# define A_TEST_HPP + +#include + +struct A_test +{ + std::string title; + std::string type; + virtual void func() = 0; +}; + +#endif + diff --git a/headers/tests_proto.hpp b/headers/tests_proto.hpp index d6e0671..c4ab59f 100644 --- a/headers/tests_proto.hpp +++ b/headers/tests_proto.hpp @@ -2,16 +2,29 @@ # define TESTS_PROTO_HPP #include +#include "A_test.hpp" // ************************************ // global declarations -struct A_test { virtual void func() = 0; }; -std::vector test_list; -void add_to_list(A_test * s1, A_test * s2, A_test * s3, A_test * s4) - { test_list.push_back(s1) - ; test_list.push_back(s2) - ; test_list.push_back(s3) - ; test_list.push_back(s4); } +std::vector< std::vector > test_list; +void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) { + + std::vector test_sub_list; + + s1->title = s; + s2->title = s; + s3->title = s; + s4->title = s; + s1->type = "int"; + s2->type = "char"; + s3->type = "std::string"; + s4->type = "mystruct"; + test_sub_list.push_back(s1); + test_sub_list.push_back(s2); + test_sub_list.push_back(s3); + test_sub_list.push_back(s4); + test_list.push_back(test_sub_list); +} // ********************************************* diff --git a/headers/tests_utils.hpp b/headers/tests_utils.hpp index d0053b6..f89add3 100644 --- a/headers/tests_utils.hpp +++ b/headers/tests_utils.hpp @@ -2,6 +2,7 @@ # define TESTS_UTILS_HPP #include "colors.h" +#include "A_test.hpp" #include #include #include @@ -24,9 +25,8 @@ // global declarations // ************************************ -struct A_test { virtual void func() = 0; }; extern std::vector test_list; -extern void add_to_list(A_test * s1, A_test * s2, A_test * s3, A_test * s4); +extern void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); // struct for tests @@ -49,39 +49,39 @@ std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { // adding each test to the list // *************************** #define TEST(f_name) \ - template struct s_ ## f_name : public A_test\ - { void func(); };\ - void f_name ()\ - { add_to_list(\ - new(s_ ## f_name )\ - ,new(s_ ## f_name )\ - ,new(s_ ## f_name )\ - ,new(s_ ## f_name )\ + template struct s_ ## f_name : public A_test\ + { void func(); };\ + void f_name ()\ + { add_to_list(\ + #f_name,\ + new(s_ ## f_name ),\ + new(s_ ## f_name ),\ + new(s_ ## f_name ),\ + new(s_ ## f_name )\ );}\ - template \ - void s_ ## f_name ::func() + template \ + void s_ ## f_name ::func() // defines // **************************************** # define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; -# define VAL(n) ito(n) +# define VAL(n) val(n) // get a value // ********************************************* -// generic template - T ito(int n) {(void)n; return (T()); + T val(int n) {(void)n; return (T()); } template <> - int ito(int n) {return (n); + int val(int n) {return (n); } template <> - char ito(int n) {return (n % 94 + 33); + char val(int n) {return (n % 94 + 33); } template <> - std::string ito(int n) { + std::string val(int n) { std::string str; std::stringstream stream; @@ -92,7 +92,7 @@ template <> return (str); } template <> - mystruct* ito(int n) { + mystruct* val(int n) { return ( new mystruct(n) ); } diff --git a/tests/main.cpp b/tests/main.cpp index 5679086..03ce661 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -91,13 +91,18 @@ int main() { // execute tests and print them : int size = test_list.size(); + int sub_size; for(int i = 0; i < size; i++) - { - std::cout - << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] " -// << test_list[i]->title << RESET "\n"; - << RESET "\n"; - test_list[i]->func(); + { + std::cout << "\n" B_YELLOW "[" << i + 1 << "/" << size << "] " + << test_list[i][0]->title << RESET << "\n"; + sub_size = test_list[i].size(); + for (int j = 0; j < sub_size; j++) + { + std::cout << "\n" << B_CYAN << "-- " << test_list[i][j]->type + << " --" << RESET "\n"; + test_list[i][j]->func(); + } } std::cout << "\n"; From 1cc5dabb7bc0f234c9fe6f324d0ac7117a3b07c3 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 15 Jun 2022 21:23:19 +0200 Subject: [PATCH 24/53] added print --- headers/tests_proto.hpp | 1 - headers/tests_utils.hpp | 14 ++++++ tests/main.cpp | 5 +- tests/tests_vectors.cpp | 107 ++++++++++++++-------------------------- 4 files changed, 52 insertions(+), 75 deletions(-) diff --git a/headers/tests_proto.hpp b/headers/tests_proto.hpp index c4ab59f..7e9631b 100644 --- a/headers/tests_proto.hpp +++ b/headers/tests_proto.hpp @@ -29,7 +29,6 @@ void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) // ********************************************* // prototypes -void test_simple(); void tests_vector_constructor(); void tests_vector_operator_assignation(); void tests_vector_begin(); diff --git a/headers/tests_utils.hpp b/headers/tests_utils.hpp index f89add3..6c59cad 100644 --- a/headers/tests_utils.hpp +++ b/headers/tests_utils.hpp @@ -67,6 +67,7 @@ std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { // **************************************** # define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; # define VAL(n) val(n) +# define PRINT(n) print_vector(n) // get a value @@ -98,4 +99,17 @@ template <> } +// get a value +// ********************************************* +template +void print_vector(ft::vector vec) +{ + int i = 0; + for (typename ft::vector::iterator it = vec.begin(); it != vec.end(); ++it, i++) + std::cout << "[" << i << "]" << *it << " "; + std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; +} + + #endif + diff --git a/tests/main.cpp b/tests/main.cpp index 03ce661..6426b6d 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -8,9 +8,8 @@ int main() { // VECTOR - test_simple(); -// tests_vector_constructor(); -// tests_vector_operator_assignation(); + tests_vector_constructor(); + tests_vector_operator_assignation(); // tests_vector_begin(); // tests_vector_end(); // tests_vector_rbegin(); diff --git a/tests/tests_vectors.cpp b/tests/tests_vectors.cpp index e5b1a48..32efaec 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vectors.cpp @@ -3,85 +3,50 @@ #include "tests_utils.hpp" -//TEST2(test_simple(), "test") -TEST(test_simple) +TEST(tests_vector_constructor) { // title TITLE(cplusplus.com reference) - T myints[] = {VAL(16),VAL(2),VAL(77),VAL(29)}; - ft::vector myvector (myints, myints + sizeof(myints) / sizeof(T) ); + // constructors used in the same order as described above: + ft::vector first; // empty vector of ints + ft::vector second (4,VAL(100)); // four ints with value 100 + ft::vector third (second.begin(),second.end()); // iterating through second + ft::vector fourth (third); // a copy of third - for (typename ft::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; + // the iterator constructor can also be used to construct from arrays: + T myints[] = {VAL(16),VAL(2),VAL(77),VAL(29)}; + ft::vector fifth (myints, myints + sizeof(myints) / sizeof(T) ); + + PRINT(fifth); +} + +TEST(tests_vector_operator_assignation) +{ + // title + TITLE(cplusplus.com reference) + + ft::vector foo (3,VAL(0)); + ft::vector bar (5,VAL(0)); + + bar = foo; + foo = ft::vector(); + + std::cout << "Size of foo: " << int(foo.size()) << '\n'; + std::cout << "Size of bar: " << int(bar.size()) << '\n'; + + + // title + TITLE(more informations) + + std::cout << "foo:\n"; + PRINT(foo); + + std::cout << "bar:\n"; + PRINT(bar); } -//TEST2END /* -void tests_vector_constructor() -{ - TEST(vector::vector (constructor)) - { - // title - TITLE(cplusplus.com reference) - - // constructors used in the same order as described above: - ft::vector first; // empty vector of ints - ft::vector second (4,100); // four ints with value 100 - ft::vector third (second.begin(),second.end()); // iterating through second - ft::vector fourth (third); // a copy of third - - // the iterator constructor can also be used to construct from arrays: - int myints[] = {16,2,77,29}; - ft::vector fifth (myints, myints + sizeof(myints) / sizeof(int) ); - - std::cout << "The contents of fifth are:"; - for (ft::vector::iterator it = fifth.begin(); it != fifth.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND -} - -void tests_vector_operator_assignation() -{ - TEST(vector::=operator) - { - // title - TITLE(cplusplus.com reference) - - ft::vector foo (3,0); - ft::vector bar (5,0); - - bar = foo; - foo = ft::vector(); - - std::cout << "Size of foo: " << int(foo.size()) << '\n'; - std::cout << "Size of bar: " << int(bar.size()) << '\n'; - - - // title - TITLE(more informations) - - int size; - - size = foo.size(); - std::cout << "foo:\n"; - for (int i = 0; i < size; i++) - std::cout << "[" << i <<"]" << foo[i]; - std::cout << "\ncapacity: " << foo.capacity() << "\n"; - - size = bar.size(); - std::cout << "bar:\n"; - for (int i = 0; i < size; i++) - std::cout << "[" << i <<"]" << bar[i]; - std::cout << "\ncapacity: " << bar.capacity() << "\n"; - - } - TESTEND -} - void tests_vector_begin() { TEST(vector::begin) { From 5ee42020200ae6eea52e60fbf38e8da1ed7deec9 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Thu, 16 Jun 2022 18:05:28 +0200 Subject: [PATCH 25/53] implemented delete correction for leaks --- Makefile | 2 +- headers/A_test.hpp | 1 + headers/tests_utils.hpp | 50 +++-- headers/vector.hpp | 1 + templates/vector.tpp | 10 +- tests/main.cpp | 7 +- tests/tests_vectors.cpp | 403 ++++++++++++++++++---------------------- 7 files changed, 229 insertions(+), 245 deletions(-) diff --git a/Makefile b/Makefile index c1ae16b..c735690 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ RESET = "\e[0m" NAME = containers -CC = g++ +CC = clang++ EXT = cpp CFLAGS = -Wall -Wextra -Werror $(INCLUDES) diff --git a/headers/A_test.hpp b/headers/A_test.hpp index 1f4c86b..f7e774f 100644 --- a/headers/A_test.hpp +++ b/headers/A_test.hpp @@ -5,6 +5,7 @@ struct A_test { + virtual ~A_test(){}; std::string title; std::string type; virtual void func() = 0; diff --git a/headers/tests_utils.hpp b/headers/tests_utils.hpp index 6c59cad..92eb10f 100644 --- a/headers/tests_utils.hpp +++ b/headers/tests_utils.hpp @@ -23,17 +23,11 @@ #endif -// global declarations -// ************************************ -extern std::vector test_list; -extern void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); - - // struct for tests // *************************************** struct mystruct { public: - mystruct(int data = 0) {_val = new int[5]; _val[0] = data;} + mystruct(int data = 0) {_val = new int[2]; _val[0] = data; _val[1] = data;} ~mystruct() {delete[] _val;} int * get_data() const {return _val;} private: @@ -41,11 +35,21 @@ private: }; //extern std::ostream & operator<<(std::ostream & o, mystruct const & rhs); std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { - o << (*rhs).get_data()[0]; + if (rhs != NULL) + o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1]; + else + o << "NULL"; return (o); } +// global declarations +// ************************************ +extern std::vector test_list; +extern void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); +std::vector mem_list_struct; + + // adding each test to the list // *************************** #define TEST(f_name) \ @@ -67,7 +71,8 @@ std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { // **************************************** # define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; # define VAL(n) val(n) -# define PRINT(n) print_vector(n) +# define PRINT(n) print_vector(n); +# define DELETE delete_structs(); // get a value @@ -94,22 +99,39 @@ template <> } template <> mystruct* val(int n) { - - return ( new mystruct(n) ); + + mystruct *s = new mystruct(n); + mem_list_struct.push_back(s); + return ( s ); } // get a value // ********************************************* template -void print_vector(ft::vector vec) -{ + void print_vector(ft::vector vec) { + int i = 0; - for (typename ft::vector::iterator it = vec.begin(); it != vec.end(); ++it, i++) + typename ft::vector::iterator it; + typename ft::vector::iterator it_end = vec.end(); + + for (it = vec.begin(); it != it_end; ++it, i++) std::cout << "[" << i << "]" << *it << " "; std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; } +// delete vector elements +// ********************************** +void delete_structs() { + + std::vector::iterator it; + std::vector::iterator it_end = mem_list_struct.end(); + + for (it = mem_list_struct.begin(); it != it_end; ++it) + delete *it; +} + + #endif diff --git a/headers/vector.hpp b/headers/vector.hpp index 78bb779..e360b5f 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -1,3 +1,4 @@ + #ifndef VECTOR_HPP # define VECTOR_HPP diff --git a/templates/vector.tpp b/templates/vector.tpp index 8f44e93..e347503 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -138,6 +138,9 @@ VT_TPL void VT:: reserve( size_type new_cap ) { value_type * tmp_ptr; + value_type * old_ptr = _mem_ptr; + iterator first = begin(); + iterator last = end(); if (new_cap > _allocator.max_size()) throw std::length_error("reserve: new_cap > max_size"); @@ -151,10 +154,11 @@ VT_TPL void VT:: if (_mem_ptr) { - for (size_type i = 0; i < _size; i++) - tmp_ptr[i] = _mem_ptr[i]; + _mem_ptr = tmp_ptr; + _size = 0; + assign(first, last); _destroy(begin(), end()); - _allocator.deallocate(_mem_ptr, _capacity); + _allocator.deallocate(old_ptr, _capacity); } _mem_ptr = tmp_ptr; } diff --git a/tests/main.cpp b/tests/main.cpp index 6426b6d..9d93052 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -8,15 +8,15 @@ int main() { // VECTOR - tests_vector_constructor(); - tests_vector_operator_assignation(); +// tests_vector_constructor(); +// tests_vector_operator_assignation(); // tests_vector_begin(); // tests_vector_end(); // tests_vector_rbegin(); // tests_vector_rend(); // tests_vector_size(); // tests_vector_max_size(); -// tests_vector_resize(); + tests_vector_resize(); // tests_vector_capacity(); // tests_vector_empty(); // tests_vector_reserve(); @@ -101,6 +101,7 @@ int main() { std::cout << "\n" << B_CYAN << "-- " << test_list[i][j]->type << " --" << RESET "\n"; test_list[i][j]->func(); + delete test_list[i][j]; } } std::cout << "\n"; diff --git a/tests/tests_vectors.cpp b/tests/tests_vectors.cpp index 32efaec..0dd832e 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vectors.cpp @@ -46,231 +46,186 @@ TEST(tests_vector_operator_assignation) PRINT(bar); } +TEST(tests_vector_begin) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + for (int i=1; i<=5; i++) myvector.push_back(VAL(i)); + + std::cout << "myvector contains:\n"; + PRINT(myvector); +} + +TEST(tests_vector_end) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + for (int i=1; i<=5; i++) myvector.push_back(VAL(i)); + + std::cout << "myvector contains:\n"; + PRINT(myvector); +} + +TEST(tests_vector_rbegin) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (5); + + int i=0; + + typename ft::vector::reverse_iterator rit = myvector.rbegin(); + for (; rit!= myvector.rend(); ++rit) + *rit = VAL(++i); + + std::cout << "myvector contains:"; + PRINT(myvector); +} + +TEST(tests_vector_rend) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (5); // 5 default-constructed Ts + + typename ft::vector::reverse_iterator rit = myvector.rbegin(); + + int i=0; + for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit) + *rit = VAL(++i); + + std::cout << "myvector contains:"; + PRINT(myvector); +} + +TEST(tests_vector_size) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myarr; + std::cout << "0. size: " << myarr.size() << '\n'; + + for (int i=0; i<10; i++) myarr.push_back(VAL(i)); + std::cout << "1. size: " << myarr.size() << '\n'; + + myarr.insert (myarr.end(),10,VAL(100)); + std::cout << "2. size: " << myarr.size() << '\n'; + + myarr.pop_back(); + std::cout << "3. size: " << myarr.size() << '\n'; + + PRINT(myarr); +} + +TEST(tests_vector_max_size) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + // set some content in the vector: + for (int i=0; i<100; i++) myvector.push_back(VAL(i)); + + std::cout << "size: " << myvector.size() << "\n"; + std::cout << "capacity: " << myvector.capacity() << "\n"; + std::cout << "max_size: " << myvector.max_size() << "\n"; + + PRINT(myvector); +} + +TEST(tests_vector_resize) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + // set some initial content: + for (int i = 1; i < 10; i++) myvector.push_back(VAL(i)); + + myvector.resize(5); + myvector.resize(8,VAL(100)); + myvector.resize(12); + + std::cout << "myvector contains:"; + PRINT(myvector); + + + // title + TITLE(test size and capacity 1 :) + + ft::vector vector2; + + std::cout << "size: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; + + std::cout << "assign(10, 1)\n"; + vector2.assign(10, VAL(1)); + PRINT(vector2); + + std::cout << "\n"; + + std::cout << "resize(15)\n"; + vector2.resize(15); + PRINT(vector2); + + std::cout << "\n"; + + std::cout << "resize(10)\n"; + vector2.resize(10); + PRINT(vector2); + + std::cout << "\n"; + + std::cout << "resize(19)\n"; + vector2.resize(19); + PRINT(vector2); + + std::cout << "\n"; + + std::cout << "resize(20)\n"; + vector2.resize(20); + PRINT(vector2); + + std::cout << "\n"; + + std::cout << "resize(21)\n"; + vector2.resize(21); + PRINT(vector2); + + std::cout << "\n"; + + + // title + TITLE(test size and capacity 2 :) + + ft::vector vector3; + + std::cout << "size: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; + + std::cout << "assign(10, 1)\n"; + vector3.assign(10, VAL(1)); + PRINT(vector3); + + std::cout << "\n"; + + std::cout << "resize(21)\n"; + vector3.resize(21); + PRINT(vector3); + + std::cout << "\n"; + + DELETE +} + /* -void tests_vector_begin() { - TEST(vector::begin) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - for (int i=1; i<=5; i++) myvector.push_back(i); - - std::cout << "myvector contains:"; - for (ft::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND -} - -void tests_vector_end() -{ - TEST(vector::end) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - for (int i=1; i<=5; i++) myvector.push_back(i); - - std::cout << "myvector contains:"; - for (ft::vector::iterator it = myvector.begin() ; it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND -} - -void tests_vector_rbegin() -{ - TEST(vector::rbegin) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector (5); // 5 default-constructed ints - - int i=0; - - ft::vector::reverse_iterator rit = myvector.rbegin(); - for (; rit!= myvector.rend(); ++rit) - *rit = ++i; - - std::cout << "myvector contains:"; - for (ft::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND -} - -void tests_vector_rend() -{ - TEST(vector::rend) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector (5); // 5 default-constructed ints - - ft::vector::reverse_iterator rit = myvector.rbegin(); - - int i=0; - for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit) - *rit = ++i; - - std::cout << "myvector contains:"; - for (ft::vector::iterator it = myvector.begin(); it != myvector.end(); ++it) - std::cout << ' ' << *it; - std::cout << '\n'; - } - TESTEND -} - -void tests_vector_size() -{ - TEST(vector::size) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myints; - std::cout << "0. size: " << myints.size() << '\n'; - - for (int i=0; i<10; i++) myints.push_back(i); - std::cout << "1. size: " << myints.size() << '\n'; - - myints.insert (myints.end(),10,100); - std::cout << "2. size: " << myints.size() << '\n'; - - myints.pop_back(); - std::cout << "3. size: " << myints.size() << '\n'; - } - TESTEND -} - -void tests_vector_max_size() -{ - TEST(vector::max_size) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - // set some content in the vector: - for (int i=0; i<100; i++) myvector.push_back(i); - - std::cout << "size: " << myvector.size() << "\n"; - std::cout << "capacity: " << myvector.capacity() << "\n"; - std::cout << "max_size: " << myvector.max_size() << "\n"; - } - TESTEND -} - -void tests_vector_resize() -{ - TEST(vector::resize) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - // set some initial content: - for (int i = 1; i < 10; i++) myvector.push_back(i); - - myvector.resize(5); - myvector.resize(8,100); - myvector.resize(12); - - std::cout << "myvector contains:"; - for (unsigned int i = 0; i < myvector.size(); i++) - std::cout << ' ' << myvector[i]; - std::cout << '\n'; - - - // title - TITLE(test size and capacity 1 :) - - ft::vector vector2; - - std::cout << "size: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "assign(10, 1)\n"; - vector2.assign(10, 1); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(15)\n"; - vector2.resize(15); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(10)\n"; - vector2.resize(10); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(19)\n"; - vector2.resize(19); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(20)\n"; - vector2.resize(20); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector2.size() << " - capacity: " << vector2.capacity() << "\n\n"; - - std::cout << "resize(21)\n"; - vector2.resize(21); - for (unsigned int i = 0; i < vector2.size(); i++) - std::cout << "[" << i << "]" << vector2[i] << " "; - std::cout << "\n"; - - - // title - TITLE(test size and capacity 2 :) - - ft::vector vector3; - - std::cout << "size: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; - - std::cout << "assign(10, 1)\n"; - vector3.assign(10, 1); - for (unsigned int i = 0; i < vector3.size(); i++) - std::cout << "[" << i << "]" << vector3[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; - - std::cout << "resize(21)\n"; - vector3.resize(21); - for (unsigned int i = 0; i < vector3.size(); i++) - std::cout << "[" << i << "]" << vector3[i] << " "; - std::cout << "\n"; - - std::cout << "\nsize: " << vector3.size() << " - capacity: " << vector3.capacity() << "\n\n"; - } - TESTEND -} - void tests_vector_capacity() { TEST(vector::capacity) From e3151bce4e7925fede493d969f00e10b468a9940 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Thu, 16 Jun 2022 18:48:46 +0200 Subject: [PATCH 26/53] correction of valgrin error --- headers/tests_utils.hpp | 9 +++++---- tests/main.cpp | 2 +- tests/tests_vectors.cpp | 16 ++++++++++++++++ 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/headers/tests_utils.hpp b/headers/tests_utils.hpp index 92eb10f..dd5c241 100644 --- a/headers/tests_utils.hpp +++ b/headers/tests_utils.hpp @@ -47,7 +47,7 @@ std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { // ************************************ extern std::vector test_list; extern void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); -std::vector mem_list_struct; +std::vector mem_list; // adding each test to the list @@ -101,7 +101,7 @@ template <> mystruct* val(int n) { mystruct *s = new mystruct(n); - mem_list_struct.push_back(s); + mem_list.push_back(s); return ( s ); } @@ -126,10 +126,11 @@ template void delete_structs() { std::vector::iterator it; - std::vector::iterator it_end = mem_list_struct.end(); + std::vector::iterator it_end = mem_list.end(); - for (it = mem_list_struct.begin(); it != it_end; ++it) + for (it = mem_list.begin(); it != it_end; ++it) delete *it; + mem_list.clear(); } diff --git a/tests/main.cpp b/tests/main.cpp index 9d93052..0b2632c 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -15,7 +15,7 @@ int main() { // tests_vector_rbegin(); // tests_vector_rend(); // tests_vector_size(); -// tests_vector_max_size(); + tests_vector_max_size(); tests_vector_resize(); // tests_vector_capacity(); // tests_vector_empty(); diff --git a/tests/tests_vectors.cpp b/tests/tests_vectors.cpp index 0dd832e..91c2611 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vectors.cpp @@ -19,6 +19,8 @@ TEST(tests_vector_constructor) ft::vector fifth (myints, myints + sizeof(myints) / sizeof(T) ); PRINT(fifth); + + DELETE } TEST(tests_vector_operator_assignation) @@ -44,6 +46,8 @@ TEST(tests_vector_operator_assignation) std::cout << "bar:\n"; PRINT(bar); + + DELETE } TEST(tests_vector_begin) @@ -56,6 +60,8 @@ TEST(tests_vector_begin) std::cout << "myvector contains:\n"; PRINT(myvector); + + DELETE } TEST(tests_vector_end) @@ -68,6 +74,8 @@ TEST(tests_vector_end) std::cout << "myvector contains:\n"; PRINT(myvector); + + DELETE } TEST(tests_vector_rbegin) @@ -85,6 +93,8 @@ TEST(tests_vector_rbegin) std::cout << "myvector contains:"; PRINT(myvector); + + DELETE } TEST(tests_vector_rend) @@ -102,6 +112,8 @@ TEST(tests_vector_rend) std::cout << "myvector contains:"; PRINT(myvector); + + DELETE } TEST(tests_vector_size) @@ -122,6 +134,8 @@ TEST(tests_vector_size) std::cout << "3. size: " << myarr.size() << '\n'; PRINT(myarr); + + DELETE } TEST(tests_vector_max_size) @@ -139,6 +153,8 @@ TEST(tests_vector_max_size) std::cout << "max_size: " << myvector.max_size() << "\n"; PRINT(myvector); + + DELETE } TEST(tests_vector_resize) From da4ebc13fd79d956fb78b305c4291aff422b2391 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 17 Jun 2022 01:00:53 +0200 Subject: [PATCH 27/53] correction of core dump --- Makefile | 4 + headers/tests_utils.hpp | 30 ++ headers/vector.hpp | 1 - templates/vector.tpp | 751 ++++++++++++++++++++++++++++++++- tests/main.cpp | 36 +- tests/tests_vectors.cpp | 903 +++++++++++++++++----------------------- 6 files changed, 1177 insertions(+), 548 deletions(-) diff --git a/Makefile b/Makefile index c735690..e86aaee 100644 --- a/Makefile +++ b/Makefile @@ -92,6 +92,10 @@ stl: CFLAGS += -D STL stl: re ft: re +leakstl: CFLAGS += -D STL +leakstl: fclean leaks +leakft: fclean leaks + $(D_OBJS)/%.o: %.$(EXT) | $(D_OBJS) @echo $(CYAN)"compilation " $@ $(RESET) @$(CC) $(CFLAGS) -c $< -o $@ diff --git a/headers/tests_utils.hpp b/headers/tests_utils.hpp index dd5c241..1dc4941 100644 --- a/headers/tests_utils.hpp +++ b/headers/tests_utils.hpp @@ -71,6 +71,7 @@ std::vector mem_list; // **************************************** # define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; # define VAL(n) val(n) +# define TOI(n) toi(n) # define PRINT(n) print_vector(n); # define DELETE delete_structs(); @@ -106,6 +107,35 @@ template <> } +// convert a value +// ***************************************** +template + int toi(T t) {(void)t; return (0); +} +template <> + int toi(int i) {return (i); +} +template <> + int toi(char c) {return (c); +} +template <> + int toi(std::string str) { + + int i; + std::stringstream stream; + + stream << str; + stream >> i; + stream.clear(); + return (i); +} +template <> + int toi(mystruct* s) { + + return ( s->get_data()[0] ); +} + + // get a value // ********************************************* template diff --git a/headers/vector.hpp b/headers/vector.hpp index e360b5f..78bb779 100644 --- a/headers/vector.hpp +++ b/headers/vector.hpp @@ -1,4 +1,3 @@ - #ifndef VECTOR_HPP # define VECTOR_HPP diff --git a/templates/vector.tpp b/templates/vector.tpp index e347503..3a62a25 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -277,8 +277,8 @@ VT_TPL typename VT::iterator VT:: _allocator.construct(it, *(it - 1)); while (it-- != position) *(it + 1) = *it; + _allocator.destroy(position); } - _allocator.destroy(position); _allocator.construct(position, val); _size++; return (position); @@ -507,3 +507,752 @@ VT_TPL #undef VT #undef VT_TPL + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/////////////////////////////////////////////////////////////////: + + + +/////////////////////////////////////////////////////////////////: + + + + + + + + +/////////////////////////////////////////////////////////////////// + + + + + +/////////////////////////////////////////////////////////////////: + + + + + + + + +//////////////////////////////////////////////////////: + + + + + +/////////////////////////////////////////////////////////////: + + + + + +/////////////////////////////////////////////////////////// + + + + +// #define VT_TPL template +// #define VT vector +// +// namespace ft { +// +// +// +// /********************************************* +// * COPLIENS +// *********************************************/ +// // constructors ------------------------------ +// VT_TPL VT:: +// vector( const Allocator & alloc ) +// : _size(0) +// , _capacity(0) +// , _mem_ptr(NULL) +// , _allocator(alloc) { +// +// return; +// } +// VT_TPL VT:: +// vector( size_type n, const T & val, const Allocator & alloc ) +// : _size(0) +// , _capacity(0) +// , _mem_ptr(NULL) +// , _allocator(alloc) { +// +// assign(n, val); +// return; +// } +// VT_TPL template VT:: +// vector(InputIterator first, InputIterator last, const Allocator & alloc) +// : _size(0) +// , _capacity(0) +// , _mem_ptr(NULL) +// , _allocator(alloc) { +// +// assign(first, last); +// return; +// } +// // copy constructor -------------------------- +// VT_TPL VT:: +// vector( vector const & src ) +// : _size(0) +// , _capacity(0) +// , _mem_ptr(NULL) +// , _allocator(src._allocator) { +// +// *this = src; +// return; +// } +// // destructors ------------------------------- +// VT_TPL VT:: +// ~vector() { return; } +// // operator= --------------------------------- +// VT_TPL VT & VT:: +// operator=( vector const & rhs ) { +// +// vector new_vector; +// +// //Base::operator=(rhs); +// if ( this != &rhs ) +// { +// new_vector.reserve(_capacity); +// new_vector.assign(rhs.begin(), rhs.end()); +// swap(new_vector); +// //_size = rhs.size(); +// } +// return *this; +// } +// +// +// +// /************* +// * iterators : +// *************/ +// // begin ------------------------------------- +// VT_TPL typename VT::iterator VT:: +// begin() { return _mem_ptr; } +// VT_TPL typename VT::const_iterator VT:: +// begin() const { return _mem_ptr; } +// // end --------------------------------------- +// VT_TPL typename VT::iterator VT:: +// end() { return &_mem_ptr[_size]; } +// 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()); } +// // 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()); } +// +// +// +// /************ +// * capacity : +// ************/ +// // size -------------------------------------- +// VT_TPL typename VT::size_type VT:: +// size( ) const { return _size; } +// // max_size ---------------------------------- +// VT_TPL typename VT::size_type VT:: +// max_size() const { return (_allocator.max_size()); } +// // resize ------------------------------------ +// VT_TPL void VT:: +// resize(size_type n, value_type val) { +// +// if (n > _size) +// { +// if (n > _capacity) +// _increment_capacity(n); +// while (_size != n) +// { +// _allocator.construct(&_mem_ptr[_size], val); +// ++_size; +// } +// } +// else if (n < _size) +// { +// while (_size != n) +// _allocator.destroy(&_mem_ptr[--_size]); +// } +// } +// // capacity ---------------------------------- +// VT_TPL typename VT::size_type VT:: +// capacity() const { return _capacity; } +// // empty ------------------------------------- +// VT_TPL bool VT:: +// empty() const { return (_size == 0); } +// // reserve ----------------------------------- +// VT_TPL void VT:: +// reserve( size_type new_cap ) { +// +// T* new_arr; +// T* old_arr = _mem_ptr; +// +// if (new_cap > max_size()) +// throw std::length_error("vector::reserve"); +// +// if (_capacity >= new_cap) +// return ; +// new_arr = _allocator.allocate(new_cap); +// +// if (old_arr) +// { +// iterator first = begin(); +// iterator last = end(); +// _mem_ptr = new_arr; +// _size = 0; +// assign(first, last); +// _destroy(first, last); +// _allocator.deallocate(old_arr, _capacity); +// } +// else +// _mem_ptr = new_arr; +// +// _capacity = new_cap; +// +// +// // value_type * tmp_ptr; +// // value_type * old_ptr = _mem_ptr; +// // iterator first = begin(); +// // iterator last = end(); +// // +// // if (new_cap > _allocator.max_size()) +// // throw std::length_error("reserve: new_cap > max_size"); +// // if (_capacity == _allocator.max_size()) +// // throw std::length_error("reserve: capacity == max_size"); +// // if (new_cap <= _capacity) +// // return ; +// // +// // _capacity = new_cap; +// // tmp_ptr = _allocator.allocate(new_cap); +// // +// // if (_mem_ptr) +// // { +// // _mem_ptr = tmp_ptr; +// // _size = 0; +// // assign(first, last); +// // _destroy(begin(), end()); +// // _allocator.deallocate(old_ptr, _capacity); +// // } +// // _mem_ptr = tmp_ptr; +// } +// +// +// +// /****************** +// * element access : +// ******************/ +// // operator[] -------------------------------- +// VT_TPL typename VT::reference VT:: +// operator[](size_type n) { return _mem_ptr[n]; } +// VT_TPL typename VT::const_reference VT:: +// operator[](size_type n) const { return _mem_ptr[n]; } +// // at ---------------------------------------- +// VT_TPL typename VT::reference VT:: +// at(size_type n) { +// +// if (n >= _size) +// throw std::out_of_range("vector out of range"); +// return (_mem_ptr[n]); +// } +// VT_TPL typename VT::const_reference VT:: +// at(size_type n) const { +// +// if (n >= _size) +// throw std::out_of_range("vector out of range"); +// return (_mem_ptr[n]); +// } +// // front ------------------------------------- +// VT_TPL typename VT::reference VT:: +// front() { return (*_mem_ptr); } +// VT_TPL typename VT::const_reference VT:: +// front() const { return (*_mem_ptr); } +// // back -------------------------------------- +// VT_TPL typename VT::reference VT:: +// back() { return (_mem_ptr[_size - 1]); } +// VT_TPL typename VT::const_reference VT:: +// back() const { return (_mem_ptr[_size - 1]); } +// +// +// +// /************* +// * modifiers : +// *************/ +// // assign ------------------------------------ +// VT_TPL template +// typename enable_if< !is_integral::value,void >::type VT:: +// assign( InputIterator first, InputIterator last) { +// +// _assign(first, last, typename iterator_traits::iterator_category()); +// +// // InputIterator tmp = first; +// // unsigned int range = 0; +// // +// // clear(); +// // +// // while (tmp++ != last) +// // range++; +// // if (range >= _capacity) +// // _increment_capacity(range); +// // while (first != last) +// // { +// // _allocator.construct(&_mem_ptr[_size], *first); +// // first++; +// // _size++; +// // } +// } +// VT_TPL +// template < typename InputIt > +// void VT:: +// _assign(InputIt first, InputIt last, std::input_iterator_tag) +// { +// clear(); +// +// while (first != last) +// { +// if (_size + 1 > _capacity) +// _increment_capacity(_size + 1); +// _allocator.construct(&_mem_ptr[_size], *first); +// ++first; +// ++_size; +// } +// } +// VT_TPL +// template < typename ForwardIt > +// void VT:: +// _assign(ForwardIt first, ForwardIt last, std::forward_iterator_tag) +// { +// clear(); +// +// difference_type diff = std::distance(first, last); +// if (diff < 0) +// throw std::logic_error("Wrong iterator order"); +// +// if (static_cast(diff) > _capacity) +// _increment_capacity(diff); +// +// while (first != last) +// { +// _allocator.construct(&_mem_ptr[_size], *first); +// ++first; +// ++_size; +// } +// } +// +// +// VT_TPL void VT:: +// assign( size_type n, const T & val ) { +// +// if (n > _allocator.max_size()) +// throw std::length_error("assign: n > max_size"); +// +// value_type * tmp_ptr; +// +// _destroy(begin(), end()); +// if (n > _capacity) +// { +// _capacity = n; +// tmp_ptr = _allocator.allocate(n); +// if (_mem_ptr) +// _allocator.deallocate(_mem_ptr, _capacity); +// _mem_ptr = tmp_ptr; +// } +// _size = n; +// while (n) +// _allocator.construct(&_mem_ptr[--n], val); +// } +// // push_back --------------------------------- +// VT_TPL void VT:: +// push_back( const value_type & element ) { +// +// if (_size >= _capacity) +// _increment_capacity(1); +// _allocator.construct(&_mem_ptr[_size], element); +// _size++; +// } +// // pop_back ---------------------------------- +// VT_TPL void VT:: +// pop_back() { _allocator.destroy(end() - 1); _size--; } +// // insert ------------------------------------ +// VT_TPL typename VT::iterator VT:: +// insert(iterator pos, const value_type& value) { +// // insert(iterator position, const value_type& val) { +// +// if (_size + 1 > _capacity) +// { +// difference_type offset = pos - begin(); +// _increment_capacity(_size + 1); +// pos = begin() + offset; +// } +// +// iterator it_end = end(); +// if (pos != it_end) +// { +// iterator i = it_end; +// --i; +// _allocator.construct(i + 1, *i); +// while (i != pos) +// { +// --i; +// *(i + 1) = *i; +// } +// _allocator.destroy(pos); +// } +// _allocator.construct(pos, value); +// _size += 1; +// return (pos); +// +// +// +// // difference_type distance; +// // iterator it; +// // +// // if (_size + 1 > _capacity) +// // { +// // distance = position - begin(); +// // _increment_capacity(1); +// // position = begin() + distance; +// // } +// // it = end(); +// // if (position != it) +// // { +// // _allocator.construct(it, *(it - 1)); +// // while (it-- != position) +// // *(it + 1) = *it; +// // } +// // _allocator.destroy(position); +// // _allocator.construct(position, val); +// // _size++; +// // return (position); +// } +// VT_TPL void VT:: +// insert(iterator pos, size_type count, const value_type& value) { +// // insert(iterator position, size_type n, const value_type& val) { +// +// if (_size + count > _capacity) +// { +// difference_type offset = pos - begin(); +// // _auto_realloc(_size + count); +// _increment_capacity(count); +// pos = begin() + offset; +// } +// +// iterator it_end = end(); +// if (pos != it_end) +// { +// iterator i = it_end; +// while (i + count != it_end && i != pos) +// { +// --i; +// _allocator.construct(i + count, *i); +// } +// while (i != pos) +// { +// --i; +// *(i + count) = *i; +// } +// // _destroy_objects(pos, std::min(pos + count, it_end)); +// _destroy(pos, std::min(pos + count, it_end)); +// } +// +// iterator last = pos + count; +// while (pos != last) +// { +// _allocator.construct(pos, value); +// ++pos; +// } +// _size += count; +// +// // difference_type distance; +// // iterator it_end; +// // iterator it; +// // +// // if (_size + n > _capacity) +// // { +// // distance = position - begin(); +// // _increment_capacity(n); +// // position = begin() + distance; +// // } +// // +// // it_end = end(); +// // if (position != it_end) +// // { +// // it = it_end; +// // while (it + n != it_end && it != position) +// // { +// // it--; +// // _allocator.construct(it + n, *it); +// // } +// // while (it != position) +// // { +// // it--; +// // *(it + n) = *it; +// // } +// // _destroy(position, std::min(position + n, it_end)); +// // } +// // +// // for (size_type i = 0; i < n; i++, position++) +// // _allocator.construct(position, val); +// // _size += n; +// } +// VT_TPL template +// typename enable_if< !is_integral::value,void >::type VT:: +// insert(iterator position, InputIterator first, InputIterator last) { +// +// difference_type dist; +// difference_type n; +// iterator it_end; +// iterator it; +// +// n = std::distance(first, last); +// if (_size + n > _capacity) +// { +// dist = position - begin(); +// _increment_capacity(n); +// position = begin() + dist; +// } +// +// it_end = end(); +// if (position != it_end) +// { +// it = it_end; +// while (it + n != it_end && it != position) +// { +// it--; +// _allocator.construct(it + n, *it); +// } +// while (it != position) +// { +// it--; +// *(it + n) = *it; +// } +// _destroy(position, std::min(position + n, it_end)); +// } +// +// while (first != last) +// { +// _allocator.construct(position, *first); +// ++position; +// ++first; +// } +// +// _size += n; +// } +// // erase ------------------------------------- +// VT_TPL typename VT::iterator VT:: +// erase(iterator position) { +// +// iterator i = position; +// iterator it_end = end() - 1; +// +// while (i != it_end) +// { +// *i = *(i + 1); +// ++i; +// } +// _allocator.destroy(it_end); +// _size -= 1; +// return (position); +// } +// VT_TPL typename VT::iterator VT:: +// erase(iterator first, iterator last) { +// +// iterator it_end = end(); +// difference_type diff = std::distance(first, last); +// +// if (diff <= 0) +// return (first); +// +// it_end = end(); +// while (last != it_end) +// { +// *first = *last; +// first++; +// last++; +// } +// _destroy(it_end - diff, it_end); +// _size -= diff; +// +// return (first); +// } +// // swap -------------------------------------- +// VT_TPL void VT:: +// swap(vector& x) { +// +// T* tmp_mem_ptr; +// size_type tmp_size; +// size_type tmp_capacity; +// +// tmp_mem_ptr = x._mem_ptr; +// tmp_size = x._size; +// tmp_capacity = x._capacity; +// +// x._mem_ptr = _mem_ptr; +// x._size = _size; +// x._capacity = _capacity; +// +// _mem_ptr = tmp_mem_ptr; +// _size = tmp_size; +// _capacity = tmp_capacity; +// } +// // clear ------------------------------------- +// VT_TPL void VT:: +// clear() { _destroy(begin(), end()); _size = 0; } +// +// +// +// /************* +// * allocator : +// *************/ +// // get_allocator ----------------------------- +// VT_TPL typename VT::allocator_type VT:: +// get_allocator() const { return (_allocator); } +// +// +// +// /********************************************* +// * PRIVATE MEMBER FUNCTIONS +// *********************************************/ +// VT_TPL void VT:: +// _destroy(iterator first, iterator last) { +// +// while (first != last) +// { +// _allocator.destroy(first); +// first++; +// } +// } +// VT_TPL void VT:: +// _increment_capacity(size_type min_new_cap) { +// // _increment_capacity(size_type n) { +// +// size_type new_cap; +// +// if (_capacity == max_size()) +// throw std::length_error("vector::reserve"); +// new_cap = std::min(max_size() / 2, _size) * 2; +// new_cap = std::max(new_cap, min_new_cap); +// reserve(new_cap); +// +// +// // size_type res; +// // +// // res = std::max(_size * 2, n); +// // reserve(std::min(res, _allocator.max_size())); +// } +// +// +// +// /********************************************* +// * 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 +// #undef VT_TPL +// diff --git a/tests/main.cpp b/tests/main.cpp index 0b2632c..fb2fc49 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -8,26 +8,26 @@ int main() { // VECTOR -// tests_vector_constructor(); -// tests_vector_operator_assignation(); -// tests_vector_begin(); -// tests_vector_end(); -// tests_vector_rbegin(); -// tests_vector_rend(); -// tests_vector_size(); + tests_vector_constructor(); + tests_vector_operator_assignation(); + tests_vector_begin(); + tests_vector_end(); + tests_vector_rbegin(); + tests_vector_rend(); + tests_vector_size(); tests_vector_max_size(); tests_vector_resize(); -// tests_vector_capacity(); -// tests_vector_empty(); -// tests_vector_reserve(); -// tests_vector_operator_access(); -// tests_vector_at(); -// tests_vector_front(); -// tests_vector_back(); -// tests_vector_assign(); -// tests_vector_push_back(); -// tests_vector_pop_back(); -// tests_vector_insert(); + tests_vector_capacity(); + tests_vector_empty(); + tests_vector_reserve(); + tests_vector_operator_access(); + tests_vector_at(); + tests_vector_front(); + tests_vector_back(); + tests_vector_assign(); + tests_vector_push_back(); + tests_vector_pop_back(); + tests_vector_insert(); // tests_vector_erase(); // tests_vector_swap(); // tests_vector_clear(); diff --git a/tests/tests_vectors.cpp b/tests/tests_vectors.cpp index 91c2611..f624392 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vectors.cpp @@ -1,3 +1,4 @@ + #ifndef TESTS_VECTORS_CPP #define TESTS_VECTORS_CPP @@ -241,535 +242,381 @@ TEST(tests_vector_resize) DELETE } +TEST(tests_vector_capacity) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + // set some content in the vector: + for (int i=0; i<100; i++) myvector.push_back(VAL(i)); + + std::cout << "size: " << (int) myvector.size() << '\n'; + std::cout << "capacity: " << (int) myvector.capacity() << '\n'; + std::cout << "max_size: " << (int) myvector.max_size() << '\n'; + + DELETE +} + +TEST(tests_vector_empty) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + int sum (0); + + for (int i=1;i<=10;i++) myvector.push_back(VAL(i)); + + while (!myvector.empty()) + { + sum+=TOI(myvector.back()); + myvector.pop_back(); + } + + std::cout << "total: " << sum << '\n'; + + DELETE +} + +TEST(tests_vector_reserve) +{ + // title + TITLE(cplusplus.com reference :) + + typename ft::vector::size_type sz; + ft::vector foo; + + sz = foo.capacity(); + std::cout << "making foo grow:\n"; + for (int i=0; i<100; ++i) { + foo.push_back(VAL(i)); + if (sz!=foo.capacity()) { + sz = foo.capacity(); + std::cout << "capacity changed: " << sz << '\n'; + } + } + + ft::vector bar; + + sz = bar.capacity(); + bar.reserve(100); // this is the only difference with foo above + std::cout << "making bar grow:\n"; + for (int i=0; i<100; ++i) { + bar.push_back(VAL(i)); + if (sz!=bar.capacity()) { + sz = bar.capacity(); + std::cout << "capacity changed: " << sz << '\n'; + } + } + + DELETE +} + +TEST(tests_vector_operator_access) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (10); // 10 zero-initialized elements + typename ft::vector::size_type sz = myvector.size(); + + // assign some values: + for (unsigned i=0; i myvector (10); // 10 zero-initialized ints + + // assign some values: + for (unsigned i=0; i myvector; + + myvector.push_back(VAL(78)); + myvector.push_back(VAL(16)); + + // now front equals 78, and back 16 + + //myvector.front() -= myvector.back(); + + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + + PRINT(myvector) + + DELETE +} + +TEST(tests_vector_back) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + myvector.push_back(VAL(78)); + myvector.push_back(VAL(16)); + + // now front equals 78, and back 16 + + // myvector.front() -= myvector.back(); + std::cout << "myvector.front() is now " << myvector.front() << '\n'; + PRINT(myvector) + + DELETE +} + +TEST(tests_vector_assign) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector first; + ft::vector second; + ft::vector third; + + first.assign (7,VAL(100)); // 7 ints with a value of 100 + + typename ft::vector::iterator it; + it=first.begin()+1; + + second.assign (it,first.end()-1); // the 5 central values of first + + T myints[] = {VAL(1776),VAL(7),VAL(4)}; + third.assign (myints,myints+3); // assigning from array. + + std::cout << "Size of first: " << int (first.size()) << '\n'; + std::cout << "Size of second: " << int (second.size()) << '\n'; + std::cout << "Size of third: " << int (third.size()) << '\n'; + + // title + TITLE(capacity tests of assignation :) + + ft::vector myvector; + + std::cout << "capacity before assignation : " << myvector.capacity() << "\n"; + + std::cout << "\nassign 1\n"; + myvector.assign(1, VAL(12)); + PRINT(myvector) + + std::cout << "\nassign 3\n"; + myvector.assign(3, VAL(12)); + PRINT(myvector) + + std::cout << "\nassign 7268\n"; + myvector.assign(7268, VAL(12)); + PRINT(myvector) + + + // title + TITLE(tests of iterators :) + + ft::vector int_vector_1; + ft::vector int_vector_2; + ft::vector int_vector_3; + ft::vector it_vector; + + std::cout << "\nassign 1\n"; + int_vector_1.assign(1, VAL(12)); + it_vector.assign(int_vector_1.begin(), int_vector_1.end()); + PRINT(it_vector) + + std::cout << "\nassign 0\n"; + int_vector_2.assign(1, VAL(6)); + it_vector.assign(int_vector_2.begin(), int_vector_2.end() - 1); + PRINT(it_vector) + + std::cout << "\nassign 266 - 13 - 172 = 81\n"; + int_vector_3.assign(266, VAL(1)); + it_vector.assign(int_vector_3.begin() + 13, int_vector_3.end() - 172); + PRINT(it_vector) + + DELETE +} + +TEST(tests_vector_push_back) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; + int size = sizeof(myint) / sizeof(myint[0]); + for (int i = 0; i < size; i++) + { + myvector.push_back(VAL(myint[i])); + std::cout << "[capacity : " + << std::setw(2) << myvector.capacity() << "] " + << myvector[i] << "\n"; + } + PRINT(myvector) + + // title + TITLE(big push back :) + + for (int i = 0; i < 72363; i++) +// for (int i = 0; i < 363; i++) + { + myvector.push_back(VAL(9)); + std::cout << "[" << i + << ":" << myvector.capacity() << "] "; + } + std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; + + DELETE +} + +TEST(tests_vector_pop_back) +{ + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector; + + int sum (0); + + myvector.push_back (VAL(100)); + myvector.push_back (VAL(200)); + myvector.push_back (VAL(300)); + + while (!myvector.empty()) + { + sum+=TOI(myvector.back()); + myvector.pop_back(); + } + + std::cout << "The elements of myvector add up to " << sum << '\n'; + + + // title + TITLE(check state :) + + std::cout << "size : " << myvector.size() << '\n'; + std::cout << "capacity : " << myvector.capacity() << '\n'; + + DELETE +} + +TEST(tests_vector_insert) +{ + typename ft::vector::iterator it; + + // title + TITLE(cplusplus.com reference :) + + ft::vector myvector (3,VAL(100)); + + it = myvector.begin(); + it = myvector.insert ( it , VAL(200) ); + myvector.insert (it,2,VAL(300)); + + ft::vector anothervector (2,VAL(400)); + it = myvector.begin(); + myvector.insert (it+2,anothervector.begin(),anothervector.end()); + + T myarray [] = { VAL(501),VAL(502),VAL(503) }; + myvector.insert (myvector.begin(), myarray, myarray+3); + + std::cout << "myvector contains:"; + PRINT(myvector) + + // title + TITLE(tests positions on insert(pos, value) :) + + ft::vector myvector2 (3,VAL(100)); + + it = myvector2.begin(); + std::cout << "size:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; + myvector2.insert ( it , VAL(200) ); + std::cout << "myvector contains:"; + PRINT(myvector2) + + ft::vector myvector3 (3,VAL(100)); + + it = myvector3.end(); + std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; + myvector3.insert ( it , VAL(200) ); + std::cout << "myvector contains:"; + PRINT(myvector3) + + ft::vector myvector4 (3,VAL(100)); + + it = myvector4.begin() + 2; + std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; + myvector4.insert ( it , VAL(200) ); + std::cout << "myvector contains:"; + PRINT(myvector4) + + + // title + TITLE(tests insert(pos, size, value) :) + + ft::vector myvector5; + + for (int i = 1; i <= 5; i++) + myvector5.push_back(VAL(i * 100)); + + it = myvector5.begin() + 1; + myvector5.insert ( it , VAL(150) ); + + it = myvector5.end(); + myvector5.insert (it,2,VAL(600)); + + it = myvector5.end() - 2; + myvector5.insert (it,2,VAL(550)); + + std::cout << "myvector contains:"; + PRINT(myvector5) + + + // title + TITLE(tests insert(pos, first, last) :) + + ft::vector myvector6; + + myvector6.assign(5, VAL(42)); + + it = myvector6.begin() + 2; + myvector6.insert ( it, myvector5.begin() + 3, myvector5.end() - 2 ); + PRINT(myvector6) + + DELETE +} + /* -void tests_vector_capacity() -{ - TEST(vector::capacity) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - // set some content in the vector: - for (int i=0; i<100; i++) myvector.push_back(i); - - std::cout << "size: " << (int) myvector.size() << '\n'; - std::cout << "capacity: " << (int) myvector.capacity() << '\n'; - std::cout << "max_size: " << (int) myvector.max_size() << '\n'; - } - TESTEND -} - -void tests_vector_empty() -{ - TEST(vector::empty) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - int sum (0); - - for (int i=1;i<=10;i++) myvector.push_back(i); - - while (!myvector.empty()) - { - sum += myvector.back(); - myvector.pop_back(); - } - - std::cout << "total: " << sum << '\n'; - } - TESTEND -} - -void tests_vector_reserve() -{ - TEST(vector::reserve) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector::size_type sz; - ft::vector foo; - - sz = foo.capacity(); - std::cout << "making foo grow:\n"; - for (int i=0; i<100; ++i) { - foo.push_back(i); - if (sz!=foo.capacity()) { - sz = foo.capacity(); - std::cout << "capacity changed: " << sz << '\n'; - } - } - - ft::vector bar; - - sz = bar.capacity(); - bar.reserve(100); // this is the only difference with foo above - std::cout << "making bar grow:\n"; - for (int i=0; i<100; ++i) { - bar.push_back(i); - if (sz!=bar.capacity()) { - sz = bar.capacity(); - std::cout << "capacity changed: " << sz << '\n'; - } - } - } - TESTEND -} - -void tests_vector_operator_access() -{ - TEST(vector::operator[]) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector (10); // 10 zero-initialized elements - ft::vector::size_type sz = myvector.size(); - - // assign some values: - for (unsigned i=0; i myvector (10); // 10 zero-initialized ints - - // assign some values: - for (unsigned i=0; i myvector; - - myvector.push_back(78); - myvector.push_back(16); - - // now front equals 78, and back 16 - - myvector.front() -= myvector.back(); - - std::cout << "myvector.front() is now " << myvector.front() << '\n'; - } - TESTEND -} - -void tests_vector_back() -{ - TEST(vector::back) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - myvector.push_back(78); - myvector.push_back(16); - - // now front equals 78, and back 16 - - myvector.front() -= myvector.back(); - std::cout << "myvector.front() is now " << myvector.front() << '\n'; - - - // title - TITLE(test with negatives :) - - myvector.push_back(236); - myvector.push_back(8973); - - myvector.front() -= myvector.back(); - std::cout << "myvector.front() is now " << myvector.front() << '\n'; - - - // title - TITLE(test with char :) - - ft::vector letters; - letters.push_back('o'); - letters.push_back('m'); - letters.push_back('g'); - letters.push_back('w'); - letters.push_back('t'); - letters.push_back('f'); - - if (!letters.empty()) { - std::cout << "The first character is '" << letters.front() << "'.\n"; - } - } - TESTEND -} - -void tests_vector_assign() -{ - TEST(vector::assign) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector first; - ft::vector second; - ft::vector third; - - first.assign (7,100); // 7 ints with a value of 100 - - ft::vector::iterator it; - it=first.begin()+1; - - second.assign (it,first.end()-1); // the 5 central values of first - - int myints[] = {1776,7,4}; - third.assign (myints,myints+3); // assigning from array. - - std::cout << "Size of first: " << int (first.size()) << '\n'; - std::cout << "Size of second: " << int (second.size()) << '\n'; - std::cout << "Size of third: " << int (third.size()) << '\n'; - - // title - TITLE(capacity tests of assignation :) - - ft::vector myvector; - int size; - - std::cout << "capacity before assignation : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 1\n"; - myvector.assign(1, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 3\n"; - myvector.assign(3, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - std::cout << "\nassign 7268\n"; - myvector.assign(7268, 12); - size = myvector.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << myvector[i] << " - "; - std::cout << "\nsize : " << size << " , capacity : " << myvector.capacity() << "\n"; - - - // title - TITLE(tests of iterators :) - - ft::vector int_vector_1; - ft::vector int_vector_2; - ft::vector int_vector_3; - ft::vector it_vector; - int ssize; - - std::cout << "\nassign 1\n"; - int_vector_1.assign(1, 12); - it_vector.assign(int_vector_1.begin(), int_vector_1.end()); - ssize = it_vector.size(); - for (int i = 0; i < ssize; i++) - std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - - std::cout << "\nassign 0\n"; - int_vector_2.assign(1, 6); - it_vector.assign(int_vector_2.begin(), int_vector_2.end() - 1); - ssize = it_vector.size(); - for (int i = 0; i < ssize; i++) - std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - - std::cout << "\nassign 266 - 13 - 172 = 81\n"; - int_vector_3.assign(266, 1); - it_vector.assign(int_vector_3.begin() + 13, int_vector_3.end() - 172); - ssize = it_vector.size(); - for (int i = 0; i < ssize; i++) - std::cout << "[" << i << "] " << it_vector[i] << " - "; - std::cout << "\nsize : " << ssize << " , capacity : " << it_vector.capacity() << "\n"; - } - TESTEND -} - -void tests_vector_push_back() -{ - TEST(vector::push_back) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - int myint[] = {12434, -2432, 12, 5345, 23, 0, -4, 387, 8432, -934723, 1}; - int size = sizeof(myint) / sizeof(myint[0]); - for (int i = 0; i < size; i++) - { - myvector.push_back(myint[i]); - std::cout << "[capacity : " - << std::setw(2) << myvector.capacity() << "] " - << myvector[i] << "\n"; - } - for (int i = 0; i < size; i++) - std::cout << "[" << std::setw(2) << i << "] " << myvector[i] << "\n"; - std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; - - - // title - TITLE(big push back :) - - for (int i = 0; i < 72363; i++) - { - myvector.push_back(9); - std::cout << "[" << i - << ":" << myvector.capacity() << "] "; - } - std::cout << " -> size : " << myvector.size() << " , capacity :" << myvector.capacity() << "\n"; - } - TESTEND -} - -void tests_vector_pop_back() -{ - TEST(vector::pop_back) - { - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector; - - int sum (0); - - myvector.push_back (100); - myvector.push_back (200); - myvector.push_back (300); - - while (!myvector.empty()) - { - sum+=myvector.back(); - myvector.pop_back(); - } - - std::cout << "The elements of myvector add up to " << sum << '\n'; - - - // title - TITLE(check state :) - - std::cout << "size : " << myvector.size() << '\n'; - std::cout << "capacity : " << myvector.capacity() << '\n'; - } - TESTEND -} - -void tests_vector_insert() -{ - TEST(vector::insert) - { - ft::vector::iterator it; - ft::vector::iterator its; - int i; - - // title - TITLE(cplusplus.com reference :) - - ft::vector myvector (3,100); - - it = myvector.begin(); - it = myvector.insert ( it , 200 ); - myvector.insert (it,2,300); - - ft::vector anothervector (2,400); - it = myvector.begin(); - myvector.insert (it+2,anothervector.begin(),anothervector.end()); - - int myarray [] = { 501,502,503 }; - myvector.insert (myvector.begin(), myarray, myarray+3); - - std::cout << "myvector contains:"; - for (it=myvector.begin(); it myvector2 (3,100); - - it = myvector2.begin(); - std::cout << "size:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; - myvector2.insert ( it , 200 ); - std::cout << "myvector contains:"; - for (it = myvector2.begin(); it < myvector2.end(); it++) - std::cout << ' ' << *it; - std::cout << "\nsize:" << myvector2.size() << " capacity:" << myvector2.capacity() << "\n"; - - ft::vector myvector3 (3,100); - - it = myvector3.end(); - std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; - myvector3.insert ( it , 200 ); - std::cout << "myvector contains:"; - for (it = myvector3.begin(); it < myvector3.end(); it++) - std::cout << ' ' << *it; - std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; - - - // title - TITLE(tests positions on insert(pos, value) with struct :) - - ft::vector myvector4; - mystruct *s; - - i = 0; - while (i < 3) - { - s = new mystruct(i++); - myvector4.push_back(s); - } - - its = myvector4.begin(); - std::cout << "size:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - s = new mystruct(i++); - myvector4.insert ( its , s ); - std::cout << "myvector contains:"; - for (its = myvector4.begin(); its < myvector4.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - - its = myvector4.begin() + 2; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - s = new mystruct(i++); - myvector4.insert ( its , s ); - std::cout << "myvector contains:"; - for (its = myvector4.begin(); its < myvector4.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - - its = myvector4.end(); - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - s = new mystruct(i++); - myvector4.insert ( its , s ); - std::cout << "myvector contains:"; - for (its = myvector4.begin(); its < myvector4.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector4.size() << " capacity:" << myvector4.capacity() << "\n"; - - - // title - TITLE(tests insert(pos, size, value) :) - - ft::vector myvector5; - - for (i = 1; i <= 5; i++) - myvector5.push_back(i * 100); - - it = myvector5.begin() + 1; - myvector5.insert ( it , 150 ); - - it = myvector5.end(); - myvector5.insert (it,2,600); - - it = myvector5.end() - 2; - myvector5.insert (it,2,550); - - std::cout << "myvector contains:"; - for (it = myvector5.begin(); it < myvector5.end(); it++) - std::cout << ' ' << *it; - std::cout << '\n'; - std::cout << "\nsize:" << myvector5.size() << " capacity:" << myvector5.capacity() << "\n"; - - - // title - TITLE(tests positions on insert(pos, value) with struct :) - - ft::vector myvector6; - - i = 1; - while (i <= 5) - { - s = new mystruct(i++ * 100); - myvector6.push_back(s); - } - - its = myvector6.begin() + 1; - s = new mystruct(150); - myvector6.insert ( its , s ); - - its = myvector6.end(); - s = new mystruct(600); - myvector6.insert ( its, 2, s ); - - its = myvector6.end() - 2; - s = new mystruct(550); - myvector6.insert ( its, 2, s ); - - std::cout << "myvector contains:"; - for (its = myvector6.begin(); its < myvector6.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector6.size() << " capacity:" << myvector6.capacity() << "\n"; - - - // title - TITLE(tests insert(pos, first, last) with struct :) - - ft::vector myvector7; - - for (i = 0; i < 5; i++) - { - s = new mystruct(42); - myvector7.push_back(s); - } - - its = myvector7.begin() + 2; - myvector7.insert ( its, myvector6.begin() + 3, myvector6.end() - 2 ); - - std::cout << "myvector contains:"; - for (its = myvector7.begin(); its < myvector7.end(); its++) - std::cout << ' ' << **its; - std::cout << "\nsize:" << myvector7.size() << " capacity:" << myvector7.capacity() << "\n"; - } - TESTEND -} - void tests_vector_erase() { TEST(vector::erase) From df6332b4964b70d17d92c5b6fc79cc81c5076d27 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 17 Jun 2022 01:20:46 +0200 Subject: [PATCH 28/53] all vector tests pass --- tests/main.cpp | 14 +- tests/tests_vectors.cpp | 501 ++++++++++++++++++---------------------- 2 files changed, 235 insertions(+), 280 deletions(-) diff --git a/tests/main.cpp b/tests/main.cpp index fb2fc49..ef91e8f 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -28,13 +28,13 @@ int main() { tests_vector_push_back(); tests_vector_pop_back(); tests_vector_insert(); -// tests_vector_erase(); -// tests_vector_swap(); -// tests_vector_clear(); -// tests_vector_get_allocator(); -// tests_vector_relational_operators(); -// tests_vector_swap_non_member(); -// tests_vector_reverse_iterators(); + tests_vector_erase(); + 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/tests_vectors.cpp b/tests/tests_vectors.cpp index f624392..9576855 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vectors.cpp @@ -488,7 +488,6 @@ TEST(tests_vector_push_back) TITLE(big push back :) for (int i = 0; i < 72363; i++) -// for (int i = 0; i < 363; i++) { myvector.push_back(VAL(9)); std::cout << "[" << i @@ -616,324 +615,280 @@ TEST(tests_vector_insert) DELETE } -/* -void tests_vector_erase() +TEST(tests_vector_erase) { - TEST(vector::erase) - { - // title - TITLE(cplusplus.com reference :) + // title + TITLE(cplusplus.com reference :) - ft::vector myvector; + ft::vector myvector; - // set some values (from 1 to 10) - for (int i=1; i<=10; i++) myvector.push_back(i); + // set some values (from 1 to 10) + for (int i=1; i<=10; i++) myvector.push_back(VAL(i)); - // erase the 6th element - myvector.erase (myvector.begin()+5); + // erase the 6th element + myvector.erase (myvector.begin()+5); - // erase the first 3 elements: - myvector.erase (myvector.begin(),myvector.begin()+3); + // erase the first 3 elements: + myvector.erase (myvector.begin(),myvector.begin()+3); - std::cout << "myvector contains:"; - for (unsigned i=0; i vector2; - // title - TITLE(test iterator bigger or equal :) - ft::vector vector2; - int size; + for (int i=1; i<=100; i++) vector2.push_back(VAL(i)); + PRINT(vector2) - for (int i=1; i<=100; i++) vector2.push_back(i); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + std::cout << "\nerase pos(7,36) :\n"; + vector2.erase(vector2.begin() + 7, vector2.begin() + 36); + PRINT(vector2) - std::cout << "\nerase pos(7,36) :\n"; - vector2.erase(vector2.begin() + 7, vector2.begin() + 36); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + std::cout << "\nerase pos(46,54) :\n"; + vector2.erase(vector2.begin() + 46, vector2.begin() + 54); + PRINT(vector2) - std::cout << "\nerase pos(46,54) :\n"; - vector2.erase(vector2.begin() + 46, vector2.begin() + 54); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; + std::cout << "\nerase pos(7,7) :\n"; + vector2.erase(vector2.begin() + 7, vector2.begin() + 7); + PRINT(vector2) - std::cout << "\nerase pos(7,7) :\n"; - vector2.erase(vector2.begin() + 7, vector2.begin() + 7); - size = vector2.size(); - for (int i = 0; i < size; i++) - std::cout << "[" << i << "] " << vector2[i] << " "; - std::cout << "\nsize:" << size << " capacity:" << vector2.capacity() << "\n"; - } - TESTEND + DELETE } -void tests_vector_swap() +TEST(tests_vector_swap) { - TEST(vector::swap) - { - // title - TITLE(cplusplus.com reference :) + // 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 + ft::vector foo (3,VAL(100)); // three ints with a value of 100 + ft::vector bar (5,VAL(200)); // five ints with a value of 200 - foo.swap(bar); + foo.swap(bar); - std::cout << "foo contains:"; - for (unsigned i=0; i myvector; - myvector.push_back (100); - myvector.push_back (200); - myvector.push_back (300); + ft::vector myvector; + myvector.push_back (VAL(100)); + myvector.push_back (VAL(200)); + myvector.push_back (VAL(300)); - std::cout << "myvector contains:"; - for (unsigned i=0; i myvector; - int * p; - unsigned int i; + ft::vector myvector; + T * p; + unsigned int i; - // allocate an array with space for 5 elements using vector's allocator: - p = myvector.get_allocator().allocate(5); + // allocate an array with space for 5 elements using vector's allocator: + p = myvector.get_allocator().allocate(5); - // construct values in-place on the array: - for (i=0; i<5; i++) myvector.get_allocator().construct(&p[i],i); + // construct values in-place on the array: + for (i=0; i<5; i++) myvector.get_allocator().construct(&p[i],VAL(i)); - std::cout << "The allocated array contains:"; - for (i=0; i<5; i++) std::cout << ' ' << p[i]; - std::cout << '\n'; + std::cout << "The allocated array contains:"; + for (i=0; i<5; i++) std::cout << ' ' << p[i]; + std::cout << '\n'; - // destroy and deallocate: - for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]); - myvector.get_allocator().deallocate(p,5); - } - TESTEND + // destroy and deallocate: + for (i=0; i<5; i++) myvector.get_allocator().destroy(&p[i]); + myvector.get_allocator().deallocate(p,5); + + DELETE } -void tests_vector_relational_operators() +TEST(tests_vector_relational_operators) { - TEST(ft::relational operators) - { - // title - TITLE(cplusplus.com reference :) + // 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 + ft::vector foo (3,VAL(100)); // three ints with a value of 100 + ft::vector bar (2,VAL(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 :) + 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"; - 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 + DELETE } -void tests_vector_reverse_iterators() +TEST(tests_vector_swap_non_member) { - TEST(ft::reverse_iterator) - { - // title - TITLE(cplusplus.com reference) - TITLE(::constructor ::operator* ::operator++(int)) + // title + TITLE(cplusplus.com reference :) - 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'; + ft::vector foo (3,VAL(100)); // three ints with a value of 100 + ft::vector bar (5,VAL(200)); // five ints with a value of 200 - while ( rev_it_minus_minus != rev_begin ) - std::cout << *(--rev_it_minus_minus) << ' '; - std::cout << '\n'; + foo.swap(bar); + + std::cout << "foo contains:"; + PRINT(foo) + + std::cout << "bar contains:"; + PRINT(bar) - - // 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 + DELETE +} + +TEST(tests_vector_reverse_iterators) +{ + // title + TITLE(cplusplus.com reference) + TITLE(::constructor ::operator* ::operator++(val)) + + ft::vector myvector; + for (int i=0; i<10; i++) myvector.push_back(VAL(i)); + typedef typename 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'; + + DELETE } -*/ #endif From 64d87cb5d4bfb7856daea51f8e7eee7ae9b6eda2 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 17 Jun 2022 01:36:45 +0200 Subject: [PATCH 29/53] no more leaks in vector --- templates/vector.tpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/templates/vector.tpp b/templates/vector.tpp index 3a62a25..ef64107 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -52,7 +52,12 @@ VT_TPL VT:: } // destructors ------------------------------- VT_TPL VT:: - ~vector() { return; } + ~vector() { + + clear(); + _allocator.deallocate(_mem_ptr, _capacity); + return; +} // operator= --------------------------------- VT_TPL VT & VT:: operator=( vector const & rhs ) { @@ -152,15 +157,14 @@ VT_TPL void VT:: _capacity = new_cap; tmp_ptr = _allocator.allocate(new_cap); + _mem_ptr = tmp_ptr; if (_mem_ptr) { - _mem_ptr = tmp_ptr; _size = 0; assign(first, last); _destroy(begin(), end()); _allocator.deallocate(old_ptr, _capacity); } - _mem_ptr = tmp_ptr; } From a939bfc66fa3cb989b885e964c27d2bad49def0a Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 17 Jun 2022 10:46:21 +0200 Subject: [PATCH 30/53] solved pbm in vector reserve --- templates/vector.tpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/vector.tpp b/templates/vector.tpp index ef64107..ff6cabb 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -158,7 +158,7 @@ VT_TPL void VT:: tmp_ptr = _allocator.allocate(new_cap); _mem_ptr = tmp_ptr; - if (_mem_ptr) + if (old_ptr) { _size = 0; assign(first, last); From 72762a79cbe59b1847b31a16f2c530f20eb117d2 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 17 Jun 2022 15:30:58 +0200 Subject: [PATCH 31/53] re-organisation of files --- Makefile | 4 +- headers/map.hpp | 166 ++++ headers/tests.hpp | 132 +++ headers/tests_proto.hpp | 32 +- headers/tests_utils.hpp | 6 +- templates/map.tpp | 120 +++ templates/vector.tpp | 766 ------------------ tests/main.cpp | 79 +- tests/tests_map.cpp | 551 +++++++++++++ tests/tests_utils.cpp | 117 +++ tests/{tests_vectors.cpp => tests_vector.cpp} | 4 +- 11 files changed, 1165 insertions(+), 812 deletions(-) create mode 100644 headers/map.hpp create mode 100644 headers/tests.hpp create mode 100644 templates/map.tpp create mode 100644 tests/tests_map.cpp create mode 100644 tests/tests_utils.cpp rename tests/{tests_vectors.cpp => tests_vector.cpp} (99%) diff --git a/Makefile b/Makefile index e86aaee..3853e3e 100644 --- a/Makefile +++ b/Makefile @@ -51,7 +51,9 @@ INCLUDES = -I$(D_HEADERS) \ D_SRCS = ./tests #SRCS = main42.cpp SRCS = main.cpp \ - tests_vectors.cpp + tests_vector.cpp + +# tests_map.cpp D_HEADERS = ./headers HEADERS = colors.h \ diff --git a/headers/map.hpp b/headers/map.hpp new file mode 100644 index 0000000..80001fc --- /dev/null +++ b/headers/map.hpp @@ -0,0 +1,166 @@ + +#ifndef MAP_HPP +# define MAP_HPP + +//# include "colors.h" +//# include +//# include +//# include // std::allocator +//# include // std::min, std::max +//# include // out_of_range, length_error, logic_error +//# include // NULL, std::size_t, std::ptrdiff_t +// +//# include "enable_if.hpp" +//# include "is_integral.hpp" +//# include "reverse_iterator.hpp" +//# include "equal.hpp" +//# include "lexicographical_compare.hpp" + +namespace ft { + +//template < +// class T, +// class Allocator = std::allocator > +class map { + +public: + +// typedef T value_type; +// typedef Allocator allocator_type; +// typedef std::size_t size_type; +// typedef std::ptrdiff_t difference_type; +// +// typedef T * iterator; +// typedef T const * const_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; + + + + /************ + * copliens : + ************/ +//// constructors ------------------------------ +// explicit map (const key_compare& comp = key_compare(), +// const allocator_type& alloc = allocator_type()); +// template +// map (InputIterator first, InputIterator last, +// const key_compare& comp = key_compare(), +// const allocator_type& alloc = allocator_type()); +// map (const map& x); +//// destructor -------------------------------- +// ~map(); +//// operator= --------------------------------- +// map& operator= (const map& x); + + + /************* + * iterators : + *************/ +//// begin ------------------------------------- +// iterator begin(); +// const_iterator begin() const; +//// end --------------------------------------- +// iterator end(); +// const_iterator end() const; +//// rbegin ------------------------------------ +// reverse_iterator rbegin(); +// const_reverse_iterator rbegin() const; +//// rend -------------------------------------- +// reverse_iterator rend(); +// const_reverse_iterator rend() const; + + + /************ + * capacity : + ************/ +//// empty ------------------------------------- +// bool empty() const; +//// size -------------------------------------- +// size_type size() const; +//// max_size ---------------------------------- +// size_type max_size() const; + + + /****************** + * element access : + ******************/ +//// operator[] -------------------------------- +// mapped_type & operator[] (const key_type& k); + + + /************* + * modifiers : + *************/ +//// insert ------------------------------------ +// pair insert (const value_type& val); +// iterator insert (iterator position, const value_type& val); +// template +// void insert (InputIterator first, InputIterator last); +//// erase ------------------------------------- +// void erase (iterator position); +// size_type erase (const key_type& k); +// void erase (iterator first, iterator last); +//// swap -------------------------------------- +// void swap (map& x); +//// clear ------------------------------------- +// void clear(); + + + /************* + * observers : + *************/ +//// key_comp ---------------------------------- +// key_compare key_comp() const; +//// value_comp -------------------------------- +// value_compare value_comp() const; + + + /************** + * operations : + **************/ +//// find -------------------------------------- +// iterator find (const key_type& k); +// const_iterator find (const key_type& k) const; +//// count ------------------------------------- +// size_type count (const key_type& k) const; +//// lower_bound ------------------------------- +// iterator lower_bound (const key_type& k); +// const_iterator lower_bound (const key_type& k) const; +//// upper_bound ------------------------------- +// iterator upper_bound (const key_type& k); +// const_iterator upper_bound (const key_type& k) const; +//// equal_range ------------------------------- +// pair equal_range (const key_type& k) const; +// pair equal_range (const key_type& k); + + + /************* + * allocator : + *************/ +//// get_allocator ----------------------------- +// allocator_type get_allocator() const; + +private: + +// size_type _size; +// size_type _capacity; +// value_type * _mem_ptr; +// allocator_type _allocator; +// +// void _destroy(iterator first, iterator last); +// void _increment_capacity(size_type n); + +}; + +} // namespace ft + +# include "map.tpp" + +#endif + diff --git a/headers/tests.hpp b/headers/tests.hpp new file mode 100644 index 0000000..1ec119e --- /dev/null +++ b/headers/tests.hpp @@ -0,0 +1,132 @@ +#ifndef TESTS_HPP +# define TESTS_HPP + +#include "colors.h" +#include +#include +#include // std::setw() +#include // std::reverse_iterator +#include // std::make_pair +#include // std::stringstream + + + +// toogle between test ft and stl +// ************************* +#include +#include +#ifdef STL + namespace ft = std; +#else + #include "vector.hpp" + #include "reverse_iterator.hpp" +#endif + + +// global variables +// *************************************** +std::vector< std::vector > test_list; +std::vector mem_list; + + + +// global functions +// *************************************** +void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); + + +// struct for tests +// *************************************** +struct mystruct { +public: + mystruct(int data = 0); + ~mystruct(); + int * get_data() const; +private: + int * _val; +}; +std::ostream & operator<<(std::ostream & o, mystruct const * rhs); + + +// adding each test to the list +// *************************** +#define TEST(f_name) \ + template struct s_ ## f_name : public A_test\ + { void func(); };\ + void f_name ()\ + { add_to_list(\ + #f_name,\ + new(s_ ## f_name ),\ + new(s_ ## f_name ),\ + new(s_ ## f_name ),\ + new(s_ ## f_name )\ + );}\ + template \ + void s_ ## f_name ::func() + + +// defines +// **************************************** +# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; +# define VAL(n) val(n) +# define TOI(n) toi(n) +# define PRINT(n) print_vector(n); +# define DELETE delete_structs(); + + +// prototypes +// ********************************************* +// vectors +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_size(); +void tests_vector_max_size(); +void tests_vector_resize(); +void tests_vector_capacity(); +void tests_vector_empty(); +void tests_vector_reserve(); +void tests_vector_operator_access(); +void tests_vector_at(); +void tests_vector_front(); +void tests_vector_back(); +void tests_vector_assign(); +void tests_vector_push_back(); +void tests_vector_pop_back(); +void tests_vector_insert(); +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(); +// map +void tests_map_simple(); +//void tests_map_constructor(); +//void tests_map_operator_assignation(); +//void tests_map_begin(); +//void tests_map_end(); +//void tests_map_rbegin(); +//void tests_map_rend(); +//void tests_map_empty(); +//void tests_map_size(); +//void tests_map_max_size(); +//void tests_map_operator_access(); +//void tests_map_insert(); +//void tests_map_erase(); +//void tests_map_swap(); +//void tests_map_clear(); +//void tests_map_key_comp(); +//void tests_map_value_comp(); +//void tests_map_find(); +//void tests_map_count(); +//void tests_map_lower_bound(); +//void tests_map_upper_bound(); +//void tests_map_equal_range(); +//void tests_map_get_allocator(); +#endif + diff --git a/headers/tests_proto.hpp b/headers/tests_proto.hpp index 7e9631b..9485930 100644 --- a/headers/tests_proto.hpp +++ b/headers/tests_proto.hpp @@ -27,8 +27,8 @@ void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) } -// ********************************************* -// prototypes +// ************************************** +// prototypes vector void tests_vector_constructor(); void tests_vector_operator_assignation(); void tests_vector_begin(); @@ -57,5 +57,33 @@ void tests_vector_relational_operators(); void tests_vector_swap_non_member(); void tests_vector_reverse_iterators(); + +// ***************************************** +// prototypes map +void tests_map_simple(); +//void tests_map_constructor(); +//void tests_map_operator_assignation(); +//void tests_map_begin(); +//void tests_map_end(); +//void tests_map_rbegin(); +//void tests_map_rend(); +//void tests_map_empty(); +//void tests_map_size(); +//void tests_map_max_size(); +//void tests_map_operator_access(); +//void tests_map_insert(); +//void tests_map_erase(); +//void tests_map_swap(); +//void tests_map_clear(); +//void tests_map_key_comp(); +//void tests_map_value_comp(); +//void tests_map_find(); +//void tests_map_count(); +//void tests_map_lower_bound(); +//void tests_map_upper_bound(); +//void tests_map_equal_range(); +//void tests_map_get_allocator(); + + #endif diff --git a/headers/tests_utils.hpp b/headers/tests_utils.hpp index 1dc4941..3c01673 100644 --- a/headers/tests_utils.hpp +++ b/headers/tests_utils.hpp @@ -5,12 +5,14 @@ #include "A_test.hpp" #include #include -#include #include // std::setw() #include // std::reverse_iterator #include // std::make_pair #include // std::map -#include +#include // std::stringstream + +#include +#include // toogle between test ft and stl diff --git a/templates/map.tpp b/templates/map.tpp new file mode 100644 index 0000000..e0a451d --- /dev/null +++ b/templates/map.tpp @@ -0,0 +1,120 @@ + +//#define VT_TPL template +//#define VT vector + +//#define MP_TPL template < typename Key, typename T, typename Compare, typename Allocator > +//#define MP map + + +namespace ft { + + + /************ + * copliens : + ************/ +//// constructors ------------------------------ +// explicit map (const key_compare& comp = key_compare(), +// const allocator_type& alloc = allocator_type()); +// template +// map (InputIterator first, InputIterator last, +// const key_compare& comp = key_compare(), +// const allocator_type& alloc = allocator_type()); +// map (const map& x); +//// destructor -------------------------------- +// ~map(); +//// operator= --------------------------------- +// map& operator= (const map& x); + + + /************* + * iterators : + *************/ +//// begin ------------------------------------- +// iterator begin(); +// const_iterator begin() const; +//// end --------------------------------------- +// iterator end(); +// const_iterator end() const; +//// rbegin ------------------------------------ +// reverse_iterator rbegin(); +// const_reverse_iterator rbegin() const; +//// rend -------------------------------------- +// reverse_iterator rend(); +// const_reverse_iterator rend() const; + + + /************ + * capacity : + ************/ +//// empty ------------------------------------- +// bool empty() const; +//// size -------------------------------------- +// size_type size() const; +//// max_size ---------------------------------- +// size_type max_size() const; + + + /****************** + * element access : + ******************/ +//// operator[] -------------------------------- +// mapped_type & operator[] (const key_type& k); + + + /************* + * modifiers : + *************/ +//// insert ------------------------------------ +// pair insert (const value_type& val); +// iterator insert (iterator position, const value_type& val); +// template +// void insert (InputIterator first, InputIterator last); +//// erase ------------------------------------- +// void erase (iterator position); +// size_type erase (const key_type& k); +// void erase (iterator first, iterator last); +//// swap -------------------------------------- +// void swap (map& x); +//// clear ------------------------------------- +// void clear(); + + + /************* + * observers : + *************/ +//// key_comp ---------------------------------- +// key_compare key_comp() const; +//// value_comp -------------------------------- +// value_compare value_comp() const; + + + /************** + * operations : + **************/ +//// find -------------------------------------- +// iterator find (const key_type& k); +// const_iterator find (const key_type& k) const; +//// count ------------------------------------- +// size_type count (const key_type& k) const; +//// lower_bound ------------------------------- +// iterator lower_bound (const key_type& k); +// const_iterator lower_bound (const key_type& k) const; +//// upper_bound ------------------------------- +// iterator upper_bound (const key_type& k); +// const_iterator upper_bound (const key_type& k) const; +//// equal_range ------------------------------- +// pair equal_range (const key_type& k) const; +// pair equal_range (const key_type& k); + + + /************* + * allocator : + *************/ +//// get_allocator ----------------------------- +// allocator_type get_allocator() const; + +} // namespace ft + +//#undef VT +//#undef VT_TPL + diff --git a/templates/vector.tpp b/templates/vector.tpp index ff6cabb..39533b0 100644 --- a/templates/vector.tpp +++ b/templates/vector.tpp @@ -5,7 +5,6 @@ namespace ft { - /********************************************* * COPLIENS *********************************************/ @@ -64,13 +63,11 @@ VT_TPL VT & VT:: vector new_vector; - //Base::operator=(rhs); if ( this != &rhs ) { new_vector.reserve(_capacity); new_vector.assign(rhs.begin(), rhs.end()); swap(new_vector); - //_size = rhs.size(); } return *this; } @@ -460,20 +457,6 @@ VT_TPL void VT:: -/********************************************* - * NESTED CLASS - *********************************************/ -//void vector::Class::function() {} - - - -/********************************************* - * STATICS - *********************************************/ -//std::string const vector::_bar = "bar"; - - - /************************ * non-member functions : ************************/ @@ -511,752 +494,3 @@ VT_TPL #undef VT #undef VT_TPL - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -/////////////////////////////////////////////////////////////////: - - - -/////////////////////////////////////////////////////////////////: - - - - - - - - -/////////////////////////////////////////////////////////////////// - - - - - -/////////////////////////////////////////////////////////////////: - - - - - - - - -//////////////////////////////////////////////////////: - - - - - -/////////////////////////////////////////////////////////////: - - - - - -/////////////////////////////////////////////////////////// - - - - -// #define VT_TPL template -// #define VT vector -// -// namespace ft { -// -// -// -// /********************************************* -// * COPLIENS -// *********************************************/ -// // constructors ------------------------------ -// VT_TPL VT:: -// vector( const Allocator & alloc ) -// : _size(0) -// , _capacity(0) -// , _mem_ptr(NULL) -// , _allocator(alloc) { -// -// return; -// } -// VT_TPL VT:: -// vector( size_type n, const T & val, const Allocator & alloc ) -// : _size(0) -// , _capacity(0) -// , _mem_ptr(NULL) -// , _allocator(alloc) { -// -// assign(n, val); -// return; -// } -// VT_TPL template VT:: -// vector(InputIterator first, InputIterator last, const Allocator & alloc) -// : _size(0) -// , _capacity(0) -// , _mem_ptr(NULL) -// , _allocator(alloc) { -// -// assign(first, last); -// return; -// } -// // copy constructor -------------------------- -// VT_TPL VT:: -// vector( vector const & src ) -// : _size(0) -// , _capacity(0) -// , _mem_ptr(NULL) -// , _allocator(src._allocator) { -// -// *this = src; -// return; -// } -// // destructors ------------------------------- -// VT_TPL VT:: -// ~vector() { return; } -// // operator= --------------------------------- -// VT_TPL VT & VT:: -// operator=( vector const & rhs ) { -// -// vector new_vector; -// -// //Base::operator=(rhs); -// if ( this != &rhs ) -// { -// new_vector.reserve(_capacity); -// new_vector.assign(rhs.begin(), rhs.end()); -// swap(new_vector); -// //_size = rhs.size(); -// } -// return *this; -// } -// -// -// -// /************* -// * iterators : -// *************/ -// // begin ------------------------------------- -// VT_TPL typename VT::iterator VT:: -// begin() { return _mem_ptr; } -// VT_TPL typename VT::const_iterator VT:: -// begin() const { return _mem_ptr; } -// // end --------------------------------------- -// VT_TPL typename VT::iterator VT:: -// end() { return &_mem_ptr[_size]; } -// 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()); } -// // 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()); } -// -// -// -// /************ -// * capacity : -// ************/ -// // size -------------------------------------- -// VT_TPL typename VT::size_type VT:: -// size( ) const { return _size; } -// // max_size ---------------------------------- -// VT_TPL typename VT::size_type VT:: -// max_size() const { return (_allocator.max_size()); } -// // resize ------------------------------------ -// VT_TPL void VT:: -// resize(size_type n, value_type val) { -// -// if (n > _size) -// { -// if (n > _capacity) -// _increment_capacity(n); -// while (_size != n) -// { -// _allocator.construct(&_mem_ptr[_size], val); -// ++_size; -// } -// } -// else if (n < _size) -// { -// while (_size != n) -// _allocator.destroy(&_mem_ptr[--_size]); -// } -// } -// // capacity ---------------------------------- -// VT_TPL typename VT::size_type VT:: -// capacity() const { return _capacity; } -// // empty ------------------------------------- -// VT_TPL bool VT:: -// empty() const { return (_size == 0); } -// // reserve ----------------------------------- -// VT_TPL void VT:: -// reserve( size_type new_cap ) { -// -// T* new_arr; -// T* old_arr = _mem_ptr; -// -// if (new_cap > max_size()) -// throw std::length_error("vector::reserve"); -// -// if (_capacity >= new_cap) -// return ; -// new_arr = _allocator.allocate(new_cap); -// -// if (old_arr) -// { -// iterator first = begin(); -// iterator last = end(); -// _mem_ptr = new_arr; -// _size = 0; -// assign(first, last); -// _destroy(first, last); -// _allocator.deallocate(old_arr, _capacity); -// } -// else -// _mem_ptr = new_arr; -// -// _capacity = new_cap; -// -// -// // value_type * tmp_ptr; -// // value_type * old_ptr = _mem_ptr; -// // iterator first = begin(); -// // iterator last = end(); -// // -// // if (new_cap > _allocator.max_size()) -// // throw std::length_error("reserve: new_cap > max_size"); -// // if (_capacity == _allocator.max_size()) -// // throw std::length_error("reserve: capacity == max_size"); -// // if (new_cap <= _capacity) -// // return ; -// // -// // _capacity = new_cap; -// // tmp_ptr = _allocator.allocate(new_cap); -// // -// // if (_mem_ptr) -// // { -// // _mem_ptr = tmp_ptr; -// // _size = 0; -// // assign(first, last); -// // _destroy(begin(), end()); -// // _allocator.deallocate(old_ptr, _capacity); -// // } -// // _mem_ptr = tmp_ptr; -// } -// -// -// -// /****************** -// * element access : -// ******************/ -// // operator[] -------------------------------- -// VT_TPL typename VT::reference VT:: -// operator[](size_type n) { return _mem_ptr[n]; } -// VT_TPL typename VT::const_reference VT:: -// operator[](size_type n) const { return _mem_ptr[n]; } -// // at ---------------------------------------- -// VT_TPL typename VT::reference VT:: -// at(size_type n) { -// -// if (n >= _size) -// throw std::out_of_range("vector out of range"); -// return (_mem_ptr[n]); -// } -// VT_TPL typename VT::const_reference VT:: -// at(size_type n) const { -// -// if (n >= _size) -// throw std::out_of_range("vector out of range"); -// return (_mem_ptr[n]); -// } -// // front ------------------------------------- -// VT_TPL typename VT::reference VT:: -// front() { return (*_mem_ptr); } -// VT_TPL typename VT::const_reference VT:: -// front() const { return (*_mem_ptr); } -// // back -------------------------------------- -// VT_TPL typename VT::reference VT:: -// back() { return (_mem_ptr[_size - 1]); } -// VT_TPL typename VT::const_reference VT:: -// back() const { return (_mem_ptr[_size - 1]); } -// -// -// -// /************* -// * modifiers : -// *************/ -// // assign ------------------------------------ -// VT_TPL template -// typename enable_if< !is_integral::value,void >::type VT:: -// assign( InputIterator first, InputIterator last) { -// -// _assign(first, last, typename iterator_traits::iterator_category()); -// -// // InputIterator tmp = first; -// // unsigned int range = 0; -// // -// // clear(); -// // -// // while (tmp++ != last) -// // range++; -// // if (range >= _capacity) -// // _increment_capacity(range); -// // while (first != last) -// // { -// // _allocator.construct(&_mem_ptr[_size], *first); -// // first++; -// // _size++; -// // } -// } -// VT_TPL -// template < typename InputIt > -// void VT:: -// _assign(InputIt first, InputIt last, std::input_iterator_tag) -// { -// clear(); -// -// while (first != last) -// { -// if (_size + 1 > _capacity) -// _increment_capacity(_size + 1); -// _allocator.construct(&_mem_ptr[_size], *first); -// ++first; -// ++_size; -// } -// } -// VT_TPL -// template < typename ForwardIt > -// void VT:: -// _assign(ForwardIt first, ForwardIt last, std::forward_iterator_tag) -// { -// clear(); -// -// difference_type diff = std::distance(first, last); -// if (diff < 0) -// throw std::logic_error("Wrong iterator order"); -// -// if (static_cast(diff) > _capacity) -// _increment_capacity(diff); -// -// while (first != last) -// { -// _allocator.construct(&_mem_ptr[_size], *first); -// ++first; -// ++_size; -// } -// } -// -// -// VT_TPL void VT:: -// assign( size_type n, const T & val ) { -// -// if (n > _allocator.max_size()) -// throw std::length_error("assign: n > max_size"); -// -// value_type * tmp_ptr; -// -// _destroy(begin(), end()); -// if (n > _capacity) -// { -// _capacity = n; -// tmp_ptr = _allocator.allocate(n); -// if (_mem_ptr) -// _allocator.deallocate(_mem_ptr, _capacity); -// _mem_ptr = tmp_ptr; -// } -// _size = n; -// while (n) -// _allocator.construct(&_mem_ptr[--n], val); -// } -// // push_back --------------------------------- -// VT_TPL void VT:: -// push_back( const value_type & element ) { -// -// if (_size >= _capacity) -// _increment_capacity(1); -// _allocator.construct(&_mem_ptr[_size], element); -// _size++; -// } -// // pop_back ---------------------------------- -// VT_TPL void VT:: -// pop_back() { _allocator.destroy(end() - 1); _size--; } -// // insert ------------------------------------ -// VT_TPL typename VT::iterator VT:: -// insert(iterator pos, const value_type& value) { -// // insert(iterator position, const value_type& val) { -// -// if (_size + 1 > _capacity) -// { -// difference_type offset = pos - begin(); -// _increment_capacity(_size + 1); -// pos = begin() + offset; -// } -// -// iterator it_end = end(); -// if (pos != it_end) -// { -// iterator i = it_end; -// --i; -// _allocator.construct(i + 1, *i); -// while (i != pos) -// { -// --i; -// *(i + 1) = *i; -// } -// _allocator.destroy(pos); -// } -// _allocator.construct(pos, value); -// _size += 1; -// return (pos); -// -// -// -// // difference_type distance; -// // iterator it; -// // -// // if (_size + 1 > _capacity) -// // { -// // distance = position - begin(); -// // _increment_capacity(1); -// // position = begin() + distance; -// // } -// // it = end(); -// // if (position != it) -// // { -// // _allocator.construct(it, *(it - 1)); -// // while (it-- != position) -// // *(it + 1) = *it; -// // } -// // _allocator.destroy(position); -// // _allocator.construct(position, val); -// // _size++; -// // return (position); -// } -// VT_TPL void VT:: -// insert(iterator pos, size_type count, const value_type& value) { -// // insert(iterator position, size_type n, const value_type& val) { -// -// if (_size + count > _capacity) -// { -// difference_type offset = pos - begin(); -// // _auto_realloc(_size + count); -// _increment_capacity(count); -// pos = begin() + offset; -// } -// -// iterator it_end = end(); -// if (pos != it_end) -// { -// iterator i = it_end; -// while (i + count != it_end && i != pos) -// { -// --i; -// _allocator.construct(i + count, *i); -// } -// while (i != pos) -// { -// --i; -// *(i + count) = *i; -// } -// // _destroy_objects(pos, std::min(pos + count, it_end)); -// _destroy(pos, std::min(pos + count, it_end)); -// } -// -// iterator last = pos + count; -// while (pos != last) -// { -// _allocator.construct(pos, value); -// ++pos; -// } -// _size += count; -// -// // difference_type distance; -// // iterator it_end; -// // iterator it; -// // -// // if (_size + n > _capacity) -// // { -// // distance = position - begin(); -// // _increment_capacity(n); -// // position = begin() + distance; -// // } -// // -// // it_end = end(); -// // if (position != it_end) -// // { -// // it = it_end; -// // while (it + n != it_end && it != position) -// // { -// // it--; -// // _allocator.construct(it + n, *it); -// // } -// // while (it != position) -// // { -// // it--; -// // *(it + n) = *it; -// // } -// // _destroy(position, std::min(position + n, it_end)); -// // } -// // -// // for (size_type i = 0; i < n; i++, position++) -// // _allocator.construct(position, val); -// // _size += n; -// } -// VT_TPL template -// typename enable_if< !is_integral::value,void >::type VT:: -// insert(iterator position, InputIterator first, InputIterator last) { -// -// difference_type dist; -// difference_type n; -// iterator it_end; -// iterator it; -// -// n = std::distance(first, last); -// if (_size + n > _capacity) -// { -// dist = position - begin(); -// _increment_capacity(n); -// position = begin() + dist; -// } -// -// it_end = end(); -// if (position != it_end) -// { -// it = it_end; -// while (it + n != it_end && it != position) -// { -// it--; -// _allocator.construct(it + n, *it); -// } -// while (it != position) -// { -// it--; -// *(it + n) = *it; -// } -// _destroy(position, std::min(position + n, it_end)); -// } -// -// while (first != last) -// { -// _allocator.construct(position, *first); -// ++position; -// ++first; -// } -// -// _size += n; -// } -// // erase ------------------------------------- -// VT_TPL typename VT::iterator VT:: -// erase(iterator position) { -// -// iterator i = position; -// iterator it_end = end() - 1; -// -// while (i != it_end) -// { -// *i = *(i + 1); -// ++i; -// } -// _allocator.destroy(it_end); -// _size -= 1; -// return (position); -// } -// VT_TPL typename VT::iterator VT:: -// erase(iterator first, iterator last) { -// -// iterator it_end = end(); -// difference_type diff = std::distance(first, last); -// -// if (diff <= 0) -// return (first); -// -// it_end = end(); -// while (last != it_end) -// { -// *first = *last; -// first++; -// last++; -// } -// _destroy(it_end - diff, it_end); -// _size -= diff; -// -// return (first); -// } -// // swap -------------------------------------- -// VT_TPL void VT:: -// swap(vector& x) { -// -// T* tmp_mem_ptr; -// size_type tmp_size; -// size_type tmp_capacity; -// -// tmp_mem_ptr = x._mem_ptr; -// tmp_size = x._size; -// tmp_capacity = x._capacity; -// -// x._mem_ptr = _mem_ptr; -// x._size = _size; -// x._capacity = _capacity; -// -// _mem_ptr = tmp_mem_ptr; -// _size = tmp_size; -// _capacity = tmp_capacity; -// } -// // clear ------------------------------------- -// VT_TPL void VT:: -// clear() { _destroy(begin(), end()); _size = 0; } -// -// -// -// /************* -// * allocator : -// *************/ -// // get_allocator ----------------------------- -// VT_TPL typename VT::allocator_type VT:: -// get_allocator() const { return (_allocator); } -// -// -// -// /********************************************* -// * PRIVATE MEMBER FUNCTIONS -// *********************************************/ -// VT_TPL void VT:: -// _destroy(iterator first, iterator last) { -// -// while (first != last) -// { -// _allocator.destroy(first); -// first++; -// } -// } -// VT_TPL void VT:: -// _increment_capacity(size_type min_new_cap) { -// // _increment_capacity(size_type n) { -// -// size_type new_cap; -// -// if (_capacity == max_size()) -// throw std::length_error("vector::reserve"); -// new_cap = std::min(max_size() / 2, _size) * 2; -// new_cap = std::max(new_cap, min_new_cap); -// reserve(new_cap); -// -// -// // size_type res; -// // -// // res = std::max(_size * 2, n); -// // reserve(std::min(res, _allocator.max_size())); -// } -// -// -// -// /********************************************* -// * 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 -// #undef VT_TPL -// diff --git a/tests/main.cpp b/tests/main.cpp index ef91e8f..ca6944f 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,67 +1,68 @@ #include #include -#include "colors.h" #include // std::setw() -#include "tests_proto.hpp" +#include "colors.h" +#include "A_test.hpp" +//#include "tests_proto.hpp" int main() { // VECTOR - tests_vector_constructor(); - tests_vector_operator_assignation(); - tests_vector_begin(); - tests_vector_end(); - tests_vector_rbegin(); - tests_vector_rend(); - tests_vector_size(); - tests_vector_max_size(); - tests_vector_resize(); - tests_vector_capacity(); - tests_vector_empty(); - tests_vector_reserve(); - tests_vector_operator_access(); - tests_vector_at(); - tests_vector_front(); - tests_vector_back(); - tests_vector_assign(); - tests_vector_push_back(); - tests_vector_pop_back(); - tests_vector_insert(); - tests_vector_erase(); - tests_vector_swap(); - tests_vector_clear(); - tests_vector_get_allocator(); - tests_vector_relational_operators(); - tests_vector_swap_non_member(); - tests_vector_reverse_iterators(); +// tests_vector_constructor(); +// tests_vector_operator_assignation(); +// tests_vector_begin(); +// tests_vector_end(); +// tests_vector_rbegin(); +// tests_vector_rend(); +// tests_vector_size(); +// tests_vector_max_size(); +// tests_vector_resize(); +// tests_vector_capacity(); +// tests_vector_empty(); +// tests_vector_reserve(); +// tests_vector_operator_access(); +// tests_vector_at(); +// tests_vector_front(); +// tests_vector_back(); +// tests_vector_assign(); +// tests_vector_push_back(); +// tests_vector_pop_back(); +// tests_vector_insert(); +// tests_vector_erase(); +// 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_simple(); // tests_map_constructor(); // tests_map_operator_assignation(); // tests_map_begin(); // tests_map_end(); // tests_map_rbegin(); // tests_map_rend(); +// tests_map_empty(); // tests_map_size(); // tests_map_max_size(); -// tests_map_resize(); -// tests_map_capacity(); -// tests_map_empty(); -// tests_map_reserve(); // tests_map_operator_access(); -// tests_map_at(); -// tests_map_front(); -// tests_map_back(); -// tests_map_assign(); -// tests_map_push_back(); -// tests_map_pop_back(); // tests_map_insert(); // tests_map_erase(); // tests_map_swap(); // tests_map_clear(); +// tests_map_key_comp(); +// tests_map_value_comp(); +// tests_map_find(); +// tests_map_count(); +// tests_map_lower_bound(); +// tests_map_upper_bound(); +// tests_map_equal_range(); // tests_map_get_allocator(); + // STACK // tests_stack_constructor(); // tests_stack_operator_assignation(); diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp new file mode 100644 index 0000000..7af511a --- /dev/null +++ b/tests/tests_map.cpp @@ -0,0 +1,551 @@ + +#ifndef TESTS_MAP_CPP +#define TESTS_MAP_CPP + +#include "tests_utils.hpp" + +TEST(tests_map_simple) +{ + // title + TITLE(simple test) + + std::map first; + std::map::iterator it; + + first['a']=10; + first['b']=30; + first['c']=50; + first['d']=70; + + for(it=first.begin(); it!=first.end(); ++it){ + std::cout << it->first << " => " << it->second << '\n'; + } + + DELETE +} + +/* +TEST(tests_map_constructor) +{ + // title + TITLE(cplusplus.com reference) + + // bool fncomp (char lhs, char rhs) {return lhs first; + + first['a']=10; + first['b']=30; + first['c']=50; + first['d']=70; + + std::map second (first.begin(),first.end()); + + std::map third (second); + + std::map fourth; // class as Compare + + bool(*fn_pt)(char,char) = fncomp; + std::map fifth (fn_pt); // function pointer as Compare + + DELETE +} + +TEST(tests_map_operator_assignation) +{ + // title + TITLE(cplusplus.com reference) + + std::map first; + std::map second; + + first['x']=8; + first['y']=16; + first['z']=32; + + second=first; // second now contains 3 ints + first=std::map(); // and first is now empty + + std::cout << "Size of first: " << first.size() << '\n'; + std::cout << "Size of second: " << second.size() << '\n'; + + DELETE +} + +TEST(tests_map_begin) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['b'] = 100; + mymap['a'] = 200; + mymap['c'] = 300; + + // show content: + for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_end) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['b'] = 100; + mymap['a'] = 200; + mymap['c'] = 300; + + // show content: + for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_rbegin) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['x'] = 100; + mymap['y'] = 200; + mymap['z'] = 300; + + // show content: + std::map::reverse_iterator rit; + for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit) + std::cout << rit->first << " => " << rit->second << '\n'; + + DELETE +} + +TEST(tests_map_rend) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['x'] = 100; + mymap['y'] = 200; + mymap['z'] = 300; + + // show content: + std::map::reverse_iterator rit; + for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit) + std::cout << rit->first << " => " << rit->second << '\n'; + + DELETE +} + +TEST(tests_map_empty) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['a']=10; + mymap['b']=20; + mymap['c']=30; + + while (!mymap.empty()) + { + std::cout << mymap.begin()->first << " => " << mymap.begin()->second << '\n'; + mymap.erase(mymap.begin()); + } + + DELETE +} + +TEST(tests_map_size) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + mymap['a']=101; + mymap['b']=202; + mymap['c']=302; + + std::cout << "mymap.size() is " << mymap.size() << '\n'; + + DELETE +} + +TEST(tests_map_max_size) +{ + // title + TITLE(cplusplus.com reference) + + int i; + std::map mymap; + + if (mymap.max_size()>1000) + { + for (i=0; i<1000; i++) mymap[i]=0; + std::cout << "The map contains 1000 elements.\n"; + } + else std::cout << "The map could not hold 1000 elements.\n"; + + DELETE +} + +TEST(tests_map_operator_access) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['a']="an element"; + mymap['b']="another element"; + mymap['c']=mymap['b']; + + std::cout << "mymap['a'] is " << mymap['a'] << '\n'; + std::cout << "mymap['b'] is " << mymap['b'] << '\n'; + std::cout << "mymap['c'] is " << mymap['c'] << '\n'; + std::cout << "mymap['d'] is " << mymap['d'] << '\n'; + + std::cout << "mymap now contains " << mymap.size() << " elements.\n"; + + DELETE +} + +TEST(tests_map_insert) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + // first insert function version (single parameter): + mymap.insert ( std::pair('a',100) ); + mymap.insert ( std::pair('z',200) ); + + std::pair::iterator,bool> ret; + ret = mymap.insert ( std::pair('z',500) ); + if (ret.second==false) { + std::cout << "element 'z' already existed"; + std::cout << " with a value of " << ret.first->second << '\n'; + } + + // second insert function version (with hint position): + std::map::iterator it = mymap.begin(); + mymap.insert (it, std::pair('b',300)); // max efficiency inserting + mymap.insert (it, std::pair('c',400)); // no max efficiency inserting + + // third insert function version (range insertion): + std::map anothermap; + anothermap.insert(mymap.begin(),mymap.find('c')); + + // showing contents: + std::cout << "mymap contains:\n"; + for (it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + std::cout << "anothermap contains:\n"; + for (it=anothermap.begin(); it!=anothermap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_erase) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + std::map::iterator it; + + // insert some values: + mymap['a']=10; + mymap['b']=20; + mymap['c']=30; + mymap['d']=40; + mymap['e']=50; + mymap['f']=60; + + it=mymap.find('b'); + mymap.erase (it); // erasing by iterator + + mymap.erase ('c'); // erasing by key + + it=mymap.find ('e'); + mymap.erase ( it, mymap.end() ); // erasing by range + + // show content: + for (it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_swap) +{ + // title + TITLE(cplusplus.com reference) + + std::map foo,bar; + + foo['x']=100; + foo['y']=200; + + bar['a']=11; + bar['b']=22; + bar['c']=33; + + foo.swap(bar); + + std::cout << "foo contains:\n"; + for (std::map::iterator it=foo.begin(); it!=foo.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + std::cout << "bar contains:\n"; + for (std::map::iterator it=bar.begin(); it!=bar.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_clear) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['x']=100; + mymap['y']=200; + mymap['z']=300; + + std::cout << "mymap contains:\n"; + for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + mymap.clear(); + mymap['a']=1101; + mymap['b']=2202; + + std::cout << "mymap contains:\n"; + for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_key_comp) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + std::map::key_compare mycomp = mymap.key_comp(); + + mymap['a']=100; + mymap['b']=200; + mymap['c']=300; + + std::cout << "mymap contains:\n"; + + char highest = mymap.rbegin()->first; // key value of last element + + std::map::iterator it = mymap.begin(); + do { + std::cout << it->first << " => " << it->second << '\n'; + } while ( mycomp((*it++).first, highest) ); + + std::cout << '\n'; + + DELETE +} + +TEST(tests_map_value_comp) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['x']=1001; + mymap['y']=2002; + mymap['z']=3003; + + std::cout << "mymap contains:\n"; + + std::pair highest = *mymap.rbegin(); // last element + + std::map::iterator it = mymap.begin(); + do { + std::cout << it->first << " => " << it->second << '\n'; + } while ( mymap.value_comp()(*it++, highest) ); + + DELETE +} + +TEST(tests_map_find) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + std::map::iterator it; + + mymap['a']=50; + mymap['b']=100; + mymap['c']=150; + mymap['d']=200; + + it = mymap.find('b'); + if (it != mymap.end()) + mymap.erase (it); + + // print content: + std::cout << "elements in mymap:" << '\n'; + std::cout << "a => " << mymap.find('a')->second << '\n'; + std::cout << "c => " << mymap.find('c')->second << '\n'; + std::cout << "d => " << mymap.find('d')->second << '\n'; + + DELETE +} + +TEST(tests_map_count) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + char c; + + mymap ['a']=101; + mymap ['c']=202; + mymap ['f']=303; + + for (c='a'; c<'h'; c++) + { + std::cout << c; + if (mymap.count(c)>0) + std::cout << " is an element of mymap.\n"; + else + std::cout << " is not an element of mymap.\n"; + } + + DELETE +} + +TEST(tests_map_lower_bound) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + std::map::iterator itlow,itup; + + mymap['a']=20; + mymap['b']=40; + mymap['c']=60; + mymap['d']=80; + mymap['e']=100; + + itlow=mymap.lower_bound ('b'); // itlow points to b + itup=mymap.upper_bound ('d'); // itup points to e (not d!) + + mymap.erase(itlow,itup); // erases [itlow,itup) + + // print content: + for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_upper_bound) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + std::map::iterator itlow,itup; + + mymap['a']=20; + mymap['b']=40; + mymap['c']=60; + mymap['d']=80; + mymap['e']=100; + + itlow=mymap.lower_bound ('b'); // itlow points to b + itup=mymap.upper_bound ('d'); // itup points to e (not d!) + + mymap.erase(itlow,itup); // erases [itlow,itup) + + // print content: + for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) + std::cout << it->first << " => " << it->second << '\n'; + + DELETE +} + +TEST(tests_map_equal_range) +{ + // title + TITLE(cplusplus.com reference) + + std::map mymap; + + mymap['a']=10; + mymap['b']=20; + mymap['c']=30; + + std::pair::iterator,std::map::iterator> ret; + ret = mymap.equal_range('b'); + + std::cout << "lower bound points to: "; + std::cout << ret.first->first << " => " << ret.first->second << '\n'; + + std::cout << "upper bound points to: "; + std::cout << ret.second->first << " => " << ret.second->second << '\n'; + + DELETE +} + +TEST(tests_map_get_allocator) +{ + // title + TITLE(cplusplus.com reference) + + int psize; + std::map mymap; + std::pair* p; + + // allocate an array of 5 elements using mymap's allocator: + p=mymap.get_allocator().allocate(5); + + // assign some values to array + psize = sizeof(std::map::value_type)*5; + + std::cout << "The allocated array has a size of " << psize << " bytes.\n"; + + mymap.get_allocator().deallocate(p,5); + + DELETE +} + +*/ + +#endif + diff --git a/tests/tests_utils.cpp b/tests/tests_utils.cpp new file mode 100644 index 0000000..427d86a --- /dev/null +++ b/tests/tests_utils.cpp @@ -0,0 +1,117 @@ + +#include "tests.hpp" + +void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) { + + std::vector test_sub_list; + + s1->title = s; + s2->title = s; + s3->title = s; + s4->title = s; + s1->type = "int"; + s2->type = "char"; + s3->type = "std::string"; + s4->type = "mystruct"; + test_sub_list.push_back(s1); + test_sub_list.push_back(s2); + test_sub_list.push_back(s3); + test_sub_list.push_back(s4); + test_list.push_back(test_sub_list); +} + +void delete_structs() { + + std::vector::iterator it; + std::vector::iterator it_end = mem_list.end(); + + for (it = mem_list.begin(); it != it_end; ++it) + delete *it; + mem_list.clear(); +} + +template + void print_vector(ft::vector vec) { + + int i = 0; + typename ft::vector::iterator it; + typename ft::vector::iterator it_end = vec.end(); + + for (it = vec.begin(); it != it_end; ++it, i++) + std::cout << "[" << i << "]" << *it << " "; + std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; +} + +// mystruct +// ********************************************* +mystruct::mystruct(int data) {_val = new int[2]; _val[0] = data; _val[1] = data;} +mystruct::~mystruct() {delete[] _val;} +int * mystruct::get_data() const {return _val;} +std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { + if (rhs != NULL) + o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1]; + else + o << "NULL"; + return (o); +} + + +// get a value +// ********************************************* +template + T val(int n) {(void)n; return (T()); +} +template <> + int val(int n) {return (n); +} +template <> + char val(int n) {return (n % 94 + 33); +} +template <> + std::string val(int n) { + + std::string str; + std::stringstream stream; + + stream << n; + stream >> str; + stream.clear(); + return (str); +} +template <> + mystruct* val(int n) { + + mystruct *s = new mystruct(n); + mem_list.push_back(s); + return ( s ); +} + + +// convert a value +// ***************************************** +template + int toi(T t) {(void)t; return (0); +} +template <> + int toi(int i) {return (i); +} +template <> + int toi(char c) {return (c); +} +template <> + int toi(std::string str) { + + int i; + std::stringstream stream; + + stream << str; + stream >> i; + stream.clear(); + return (i); +} +template <> + int toi(mystruct* s) { + + return ( s->get_data()[0] ); +} + diff --git a/tests/tests_vectors.cpp b/tests/tests_vector.cpp similarity index 99% rename from tests/tests_vectors.cpp rename to tests/tests_vector.cpp index 9576855..5ca40fe 100644 --- a/tests/tests_vectors.cpp +++ b/tests/tests_vector.cpp @@ -1,6 +1,6 @@ -#ifndef TESTS_VECTORS_CPP -#define TESTS_VECTORS_CPP +#ifndef TESTS_VECTOR_CPP +#define TESTS_VECTOR_CPP #include "tests_utils.hpp" From 94745ca8a9b1bbe2053f5fce33260d5316bd27a9 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sat, 18 Jun 2022 17:58:14 +0200 Subject: [PATCH 32/53] resolve template specialization with inline keyword --- Makefile | 22 +- headers/tests.hpp | 132 ------------ .../includes/main.hpp | 48 ++--- .../A_test.hpp => tests/includes/tests_A.hpp | 4 +- tests/includes/tests_mystruct.hpp | 21 ++ .../tests_templates.tpp} | 47 +---- {headers => tests/includes}/tests_utils.hpp | 192 ++++++++---------- tests/main.cpp | 8 +- tests/tests_definitions.cpp | 54 +++++ tests/tests_mystruct.cpp | 19 ++ tests/tests_vector.cpp | 2 +- 11 files changed, 222 insertions(+), 327 deletions(-) delete mode 100644 headers/tests.hpp rename headers/tests_proto.hpp => tests/includes/main.hpp (65%) rename headers/A_test.hpp => tests/includes/tests_A.hpp (76%) create mode 100644 tests/includes/tests_mystruct.hpp rename tests/{tests_utils.cpp => includes/tests_templates.tpp} (53%) rename {headers => tests/includes}/tests_utils.hpp (58%) create mode 100644 tests/tests_definitions.cpp create mode 100644 tests/tests_mystruct.cpp diff --git a/Makefile b/Makefile index 3853e3e..4892a68 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ RESET = "\e[0m" NAME = containers -CC = clang++ +CC = g++ EXT = cpp CFLAGS = -Wall -Wextra -Werror $(INCLUDES) @@ -44,22 +44,22 @@ VPATH = $(D_SRCS) LIBS = F_INCLUDES = $(HEADERS:%=$(D_HEADERS)/%) \ - $(TEMPLATES:%=$(D_TEMPLATES)/%) + $(TEMPLATES:%=$(D_TEMPLATES)/%) \ + $(TESTS:%=$(D_TESTS)/%) INCLUDES = -I$(D_HEADERS) \ - -I$(D_TEMPLATES) + -I$(D_TEMPLATES) \ + -I$(D_TESTS) D_SRCS = ./tests #SRCS = main42.cpp SRCS = main.cpp \ - tests_vector.cpp - -# tests_map.cpp + tests_definitions.cpp \ + \ + tests_vector.cpp \ + tests_map.cpp D_HEADERS = ./headers HEADERS = colors.h \ - tests_utils.hpp \ - tests_proto.hpp \ - A_test.hpp \ \ enable_if.hpp \ iterator_traits.hpp \ @@ -72,6 +72,10 @@ HEADERS = colors.h \ D_TEMPLATES = ./templates TEMPLATES = vector.tpp +D_TESTS = ./tests/includes +TESTS = main.hpp \ + tests_utils.hpp + D_OBJS = builds OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) diff --git a/headers/tests.hpp b/headers/tests.hpp deleted file mode 100644 index 1ec119e..0000000 --- a/headers/tests.hpp +++ /dev/null @@ -1,132 +0,0 @@ -#ifndef TESTS_HPP -# define TESTS_HPP - -#include "colors.h" -#include -#include -#include // std::setw() -#include // std::reverse_iterator -#include // std::make_pair -#include // std::stringstream - - - -// toogle between test ft and stl -// ************************* -#include -#include -#ifdef STL - namespace ft = std; -#else - #include "vector.hpp" - #include "reverse_iterator.hpp" -#endif - - -// global variables -// *************************************** -std::vector< std::vector > test_list; -std::vector mem_list; - - - -// global functions -// *************************************** -void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); - - -// struct for tests -// *************************************** -struct mystruct { -public: - mystruct(int data = 0); - ~mystruct(); - int * get_data() const; -private: - int * _val; -}; -std::ostream & operator<<(std::ostream & o, mystruct const * rhs); - - -// adding each test to the list -// *************************** -#define TEST(f_name) \ - template struct s_ ## f_name : public A_test\ - { void func(); };\ - void f_name ()\ - { add_to_list(\ - #f_name,\ - new(s_ ## f_name ),\ - new(s_ ## f_name ),\ - new(s_ ## f_name ),\ - new(s_ ## f_name )\ - );}\ - template \ - void s_ ## f_name ::func() - - -// defines -// **************************************** -# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; -# define VAL(n) val(n) -# define TOI(n) toi(n) -# define PRINT(n) print_vector(n); -# define DELETE delete_structs(); - - -// prototypes -// ********************************************* -// vectors -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_size(); -void tests_vector_max_size(); -void tests_vector_resize(); -void tests_vector_capacity(); -void tests_vector_empty(); -void tests_vector_reserve(); -void tests_vector_operator_access(); -void tests_vector_at(); -void tests_vector_front(); -void tests_vector_back(); -void tests_vector_assign(); -void tests_vector_push_back(); -void tests_vector_pop_back(); -void tests_vector_insert(); -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(); -// map -void tests_map_simple(); -//void tests_map_constructor(); -//void tests_map_operator_assignation(); -//void tests_map_begin(); -//void tests_map_end(); -//void tests_map_rbegin(); -//void tests_map_rend(); -//void tests_map_empty(); -//void tests_map_size(); -//void tests_map_max_size(); -//void tests_map_operator_access(); -//void tests_map_insert(); -//void tests_map_erase(); -//void tests_map_swap(); -//void tests_map_clear(); -//void tests_map_key_comp(); -//void tests_map_value_comp(); -//void tests_map_find(); -//void tests_map_count(); -//void tests_map_lower_bound(); -//void tests_map_upper_bound(); -//void tests_map_equal_range(); -//void tests_map_get_allocator(); -#endif - diff --git a/headers/tests_proto.hpp b/tests/includes/main.hpp similarity index 65% rename from headers/tests_proto.hpp rename to tests/includes/main.hpp index 9485930..42a0876 100644 --- a/headers/tests_proto.hpp +++ b/tests/includes/main.hpp @@ -1,34 +1,23 @@ -#ifndef TESTS_PROTO_HPP -# define TESTS_PROTO_HPP +#ifndef MAIN_HPP +# define MAIN_HPP +#include "colors.h" +#include +#include +#include // std::setw() #include -#include "A_test.hpp" - -// ************************************ -// global declarations -std::vector< std::vector > test_list; -void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) { - - std::vector test_sub_list; - - s1->title = s; - s2->title = s; - s3->title = s; - s4->title = s; - s1->type = "int"; - s2->type = "char"; - s3->type = "std::string"; - s4->type = "mystruct"; - test_sub_list.push_back(s1); - test_sub_list.push_back(s2); - test_sub_list.push_back(s3); - test_sub_list.push_back(s4); - test_list.push_back(test_sub_list); -} +#include "tests_utils.hpp" -// ************************************** -// prototypes vector +// global variables +// *************************************** +std::vector< std::vector > test_list; +std::vector< mystruct* > mem_list; + + +// prototypes +// ********************************************* +// vectors void tests_vector_constructor(); void tests_vector_operator_assignation(); void tests_vector_begin(); @@ -56,10 +45,7 @@ void tests_vector_get_allocator(); void tests_vector_relational_operators(); void tests_vector_swap_non_member(); void tests_vector_reverse_iterators(); - - -// ***************************************** -// prototypes map +// map void tests_map_simple(); //void tests_map_constructor(); //void tests_map_operator_assignation(); diff --git a/headers/A_test.hpp b/tests/includes/tests_A.hpp similarity index 76% rename from headers/A_test.hpp rename to tests/includes/tests_A.hpp index f7e774f..5f38488 100644 --- a/headers/A_test.hpp +++ b/tests/includes/tests_A.hpp @@ -1,5 +1,5 @@ -#ifndef A_TEST_HPP -# define A_TEST_HPP +#ifndef TESTS_A_HPP +# define TESTS_A_HPP #include diff --git a/tests/includes/tests_mystruct.hpp b/tests/includes/tests_mystruct.hpp new file mode 100644 index 0000000..8f2883a --- /dev/null +++ b/tests/includes/tests_mystruct.hpp @@ -0,0 +1,21 @@ +#ifndef TESTS_MYSTRUCT_HPP +# define TESTS_MYSTRUCT_HPP + +#include + +struct mystruct { + +public: + mystruct(int data = 0); + ~mystruct(); + int * get_data() const; + +private: + int * _val; + +}; + +std::ostream & operator<<(std::ostream & o, mystruct const * rhs); + +#endif + diff --git a/tests/tests_utils.cpp b/tests/includes/tests_templates.tpp similarity index 53% rename from tests/tests_utils.cpp rename to tests/includes/tests_templates.tpp index 427d86a..442378d 100644 --- a/tests/tests_utils.cpp +++ b/tests/includes/tests_templates.tpp @@ -1,35 +1,8 @@ -#include "tests.hpp" - -void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) { - - std::vector test_sub_list; - - s1->title = s; - s2->title = s; - s3->title = s; - s4->title = s; - s1->type = "int"; - s2->type = "char"; - s3->type = "std::string"; - s4->type = "mystruct"; - test_sub_list.push_back(s1); - test_sub_list.push_back(s2); - test_sub_list.push_back(s3); - test_sub_list.push_back(s4); - test_list.push_back(test_sub_list); -} - -void delete_structs() { - - std::vector::iterator it; - std::vector::iterator it_end = mem_list.end(); - - for (it = mem_list.begin(); it != it_end; ++it) - delete *it; - mem_list.clear(); -} +#include "tests_utils.hpp" +// print vector +// ******************************************** template void print_vector(ft::vector vec) { @@ -42,20 +15,6 @@ template std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; } -// mystruct -// ********************************************* -mystruct::mystruct(int data) {_val = new int[2]; _val[0] = data; _val[1] = data;} -mystruct::~mystruct() {delete[] _val;} -int * mystruct::get_data() const {return _val;} -std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { - if (rhs != NULL) - o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1]; - else - o << "NULL"; - return (o); -} - - // get a value // ********************************************* template diff --git a/headers/tests_utils.hpp b/tests/includes/tests_utils.hpp similarity index 58% rename from headers/tests_utils.hpp rename to tests/includes/tests_utils.hpp index 3c01673..8aefeaa 100644 --- a/headers/tests_utils.hpp +++ b/tests/includes/tests_utils.hpp @@ -1,22 +1,21 @@ + #ifndef TESTS_UTILS_HPP # define TESTS_UTILS_HPP + #include "colors.h" -#include "A_test.hpp" #include #include #include // std::setw() #include // std::reverse_iterator #include // std::make_pair -#include // std::map #include // std::stringstream -#include -#include - // toogle between test ft and stl // ************************* +#include +#include #ifdef STL namespace ft = std; #else @@ -25,31 +24,41 @@ #endif -// struct for tests -// *************************************** +// defines +// **************************************** +# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; +# define VAL(n) val(n) +# define TOI(n) toi(n) +# define PRINT(n) print_vector(n); +# define DELETE delete_structs(); + + +// prototypes +// ********************************************* +struct A_test +{ + virtual ~A_test(){}; + std::string title; + std::string type; + virtual void func() = 0; +}; struct mystruct { public: - mystruct(int data = 0) {_val = new int[2]; _val[0] = data; _val[1] = data;} - ~mystruct() {delete[] _val;} - int * get_data() const {return _val;} + mystruct(int data = 0); + ~mystruct(); + int * get_data() const; private: int * _val; }; -//extern std::ostream & operator<<(std::ostream & o, mystruct const & rhs); -std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { - if (rhs != NULL) - o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1]; - else - o << "NULL"; - return (o); -} +std::ostream & operator<<(std::ostream & o, mystruct const * rhs); +void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); +void delete_structs(); -// global declarations -// ************************************ -extern std::vector test_list; -extern void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); -std::vector mem_list; +// global variables +// *************************************** +extern std::vector< std::vector > test_list; +extern std::vector< mystruct* > mem_list; // adding each test to the list @@ -69,77 +78,8 @@ std::vector mem_list; void s_ ## f_name ::func() -// defines -// **************************************** -# define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; -# define VAL(n) val(n) -# define TOI(n) toi(n) -# define PRINT(n) print_vector(n); -# define DELETE delete_structs(); - - -// get a value -// ********************************************* -template - T val(int n) {(void)n; return (T()); -} -template <> - int val(int n) {return (n); -} -template <> - char val(int n) {return (n % 94 + 33); -} -template <> - std::string val(int n) { - - std::string str; - std::stringstream stream; - - stream << n; - stream >> str; - stream.clear(); - return (str); -} -template <> - mystruct* val(int n) { - - mystruct *s = new mystruct(n); - mem_list.push_back(s); - return ( s ); -} - - -// convert a value +// templates print // ***************************************** -template - int toi(T t) {(void)t; return (0); -} -template <> - int toi(int i) {return (i); -} -template <> - int toi(char c) {return (c); -} -template <> - int toi(std::string str) { - - int i; - std::stringstream stream; - - stream << str; - stream >> i; - stream.clear(); - return (i); -} -template <> - int toi(mystruct* s) { - - return ( s->get_data()[0] ); -} - - -// get a value -// ********************************************* template void print_vector(ft::vector vec) { @@ -152,17 +92,65 @@ template std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; } +// templates get value +// ************************************* +// specialization in header, make it inline : +// https://stackoverflow.com/questions/63529059/c-specialized-method-templates-produce-multiple-definition-errors +template + T val(int n) {(void)n; return (T()); +} +template <> + inline int val(int n) {return (n); +} +template <> + inline char val(int n) {return (n % 94 + 33); +} +template <> + inline std::string val(int n) { -// delete vector elements -// ********************************** -void delete_structs() { - - std::vector::iterator it; - std::vector::iterator it_end = mem_list.end(); + std::string str; + std::stringstream stream; - for (it = mem_list.begin(); it != it_end; ++it) - delete *it; - mem_list.clear(); + stream << n; + stream >> str; + stream.clear(); + return (str); +} +template <> + inline mystruct* val(int n) { + + mystruct *s = new mystruct(n); + mem_list.push_back(s); + return ( s ); +} + + +// templates to value +// ************************************** +template + int toi(T t) {(void)t; return (0); +} +template <> + inline int toi(int i) {return (i); +} +template <> + inline int toi(char c) {return (c); +} +template <> + inline int toi(std::string str) { + + int i; + std::stringstream stream; + + stream << str; + stream >> i; + stream.clear(); + return (i); +} +template <> + inline int toi(mystruct* s) { + + return ( s->get_data()[0] ); } diff --git a/tests/main.cpp b/tests/main.cpp index ca6944f..59d518a 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -1,9 +1,5 @@ -#include -#include -#include // std::setw() -#include "colors.h" -#include "A_test.hpp" -//#include "tests_proto.hpp" + +#include "main.hpp" int main() { diff --git a/tests/tests_definitions.cpp b/tests/tests_definitions.cpp new file mode 100644 index 0000000..6f278ea --- /dev/null +++ b/tests/tests_definitions.cpp @@ -0,0 +1,54 @@ + +#include "tests_utils.hpp" + + +// functions +// ********************************************** +void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) { + + std::vector test_sub_list; + + s1->title = s; + s2->title = s; + s3->title = s; + s4->title = s; + s1->type = "int"; + s2->type = "char"; + s3->type = "std::string"; + s4->type = "mystruct"; + test_sub_list.push_back(s1); + test_sub_list.push_back(s2); + test_sub_list.push_back(s3); + test_sub_list.push_back(s4); + test_list.push_back(test_sub_list); +} +void delete_structs() { + + std::vector::iterator it; + std::vector::iterator it_end = mem_list.end(); + + for (it = mem_list.begin(); it != it_end; ++it) + delete *it; + mem_list.clear(); +} + + +// mystruct +// *********************************************** +mystruct::mystruct(int data) + {_val = new int[2]; _val[0] = data; _val[1] = data;} + +mystruct::~mystruct() + {delete[] _val;} + +int * mystruct::get_data() const + {return _val;} + +std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { + if (rhs != NULL) + o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1]; + else + o << "NULL"; + return (o); +} + diff --git a/tests/tests_mystruct.cpp b/tests/tests_mystruct.cpp new file mode 100644 index 0000000..22f488d --- /dev/null +++ b/tests/tests_mystruct.cpp @@ -0,0 +1,19 @@ + +#include "tests_mystruct.hpp" + +mystruct::mystruct(int data) + {_val = new int[2]; _val[0] = data; _val[1] = data;} + +mystruct::~mystruct() + {delete[] _val;} + +int * mystruct::get_data() const + {return _val;} + +std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { + if (rhs != NULL) + o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1]; + else + o << "NULL"; + return (o); +} diff --git a/tests/tests_vector.cpp b/tests/tests_vector.cpp index 5ca40fe..6bc1f02 100644 --- a/tests/tests_vector.cpp +++ b/tests/tests_vector.cpp @@ -11,7 +11,7 @@ TEST(tests_vector_constructor) // constructors used in the same order as described above: ft::vector first; // empty vector of ints - ft::vector second (4,VAL(100)); // four ints with value 100 + ft::vector second (4,VAL(100)); // four ints with value 100 ft::vector third (second.begin(),second.end()); // iterating through second ft::vector fourth (third); // a copy of third From 50224fb432585cc4e93e63b59bb0942555d4e6e1 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sun, 19 Jun 2022 11:49:49 +0200 Subject: [PATCH 33/53] tests are receving as much argument as necessary, and print works with map --- tests/includes/tests_A.hpp | 15 ------ tests/includes/tests_mystruct.hpp | 21 --------- tests/includes/tests_templates.tpp | 76 ------------------------------ tests/includes/tests_utils.hpp | 31 +++++++----- tests/main.cpp | 4 +- tests/tests_definitions.cpp | 26 +++++----- tests/tests_map.cpp | 13 ++--- tests/tests_mystruct.cpp | 19 -------- 8 files changed, 40 insertions(+), 165 deletions(-) delete mode 100644 tests/includes/tests_A.hpp delete mode 100644 tests/includes/tests_mystruct.hpp delete mode 100644 tests/includes/tests_templates.tpp delete mode 100644 tests/tests_mystruct.cpp diff --git a/tests/includes/tests_A.hpp b/tests/includes/tests_A.hpp deleted file mode 100644 index 5f38488..0000000 --- a/tests/includes/tests_A.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef TESTS_A_HPP -# define TESTS_A_HPP - -#include - -struct A_test -{ - virtual ~A_test(){}; - std::string title; - std::string type; - virtual void func() = 0; -}; - -#endif - diff --git a/tests/includes/tests_mystruct.hpp b/tests/includes/tests_mystruct.hpp deleted file mode 100644 index 8f2883a..0000000 --- a/tests/includes/tests_mystruct.hpp +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef TESTS_MYSTRUCT_HPP -# define TESTS_MYSTRUCT_HPP - -#include - -struct mystruct { - -public: - mystruct(int data = 0); - ~mystruct(); - int * get_data() const; - -private: - int * _val; - -}; - -std::ostream & operator<<(std::ostream & o, mystruct const * rhs); - -#endif - diff --git a/tests/includes/tests_templates.tpp b/tests/includes/tests_templates.tpp deleted file mode 100644 index 442378d..0000000 --- a/tests/includes/tests_templates.tpp +++ /dev/null @@ -1,76 +0,0 @@ - -#include "tests_utils.hpp" - -// print vector -// ******************************************** -template - void print_vector(ft::vector vec) { - - int i = 0; - typename ft::vector::iterator it; - typename ft::vector::iterator it_end = vec.end(); - - for (it = vec.begin(); it != it_end; ++it, i++) - std::cout << "[" << i << "]" << *it << " "; - std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; -} - -// get a value -// ********************************************* -template - T val(int n) {(void)n; return (T()); -} -template <> - int val(int n) {return (n); -} -template <> - char val(int n) {return (n % 94 + 33); -} -template <> - std::string val(int n) { - - std::string str; - std::stringstream stream; - - stream << n; - stream >> str; - stream.clear(); - return (str); -} -template <> - mystruct* val(int n) { - - mystruct *s = new mystruct(n); - mem_list.push_back(s); - return ( s ); -} - - -// convert a value -// ***************************************** -template - int toi(T t) {(void)t; return (0); -} -template <> - int toi(int i) {return (i); -} -template <> - int toi(char c) {return (c); -} -template <> - int toi(std::string str) { - - int i; - std::stringstream stream; - - stream << str; - stream >> i; - stream.clear(); - return (i); -} -template <> - int toi(mystruct* s) { - - return ( s->get_data()[0] ); -} - diff --git a/tests/includes/tests_utils.hpp b/tests/includes/tests_utils.hpp index 8aefeaa..7060d81 100644 --- a/tests/includes/tests_utils.hpp +++ b/tests/includes/tests_utils.hpp @@ -29,7 +29,7 @@ # define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; # define VAL(n) val(n) # define TOI(n) toi(n) -# define PRINT(n) print_vector(n); +# define PRINT(n) print(n); # define DELETE delete_structs(); @@ -51,7 +51,7 @@ private: int * _val; }; std::ostream & operator<<(std::ostream & o, mystruct const * rhs); -void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4); +void add_to_list(std::string title, std::string type, A_test* test); void delete_structs(); @@ -66,14 +66,12 @@ extern std::vector< mystruct* > mem_list; #define TEST(f_name) \ template struct s_ ## f_name : public A_test\ { void func(); };\ - void f_name ()\ - { add_to_list(\ - #f_name,\ - new(s_ ## f_name ),\ - new(s_ ## f_name ),\ - new(s_ ## f_name ),\ - new(s_ ## f_name )\ - );}\ + void f_name () {\ + add_to_list(#f_name, "int", new(s_ ## f_name ));\ + add_to_list("", "char", new(s_ ## f_name ));\ + add_to_list("", "std::string", new(s_ ## f_name ));\ + add_to_list("", "mystruct*", new(s_ ## f_name ));\ + }\ template \ void s_ ## f_name ::func() @@ -81,7 +79,7 @@ extern std::vector< mystruct* > mem_list; // templates print // ***************************************** template - void print_vector(ft::vector vec) { + void print(ft::vector vec) { int i = 0; typename ft::vector::iterator it; @@ -91,6 +89,17 @@ template std::cout << "[" << i << "]" << *it << " "; std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; } +template + void print(ft::map ma) { + + int i = 0; + typename ft::map::iterator it; + typename ft::map::iterator it_end = ma.end(); + + for (it = ma.begin(); it != it_end; ++it, i++) + std::cout << "[" << i << "]" << it->first << ":" << it->second << " "; + std::cout << "\nsize:" << ma.size() << "\n"; +} // templates get value // ************************************* diff --git a/tests/main.cpp b/tests/main.cpp index 59d518a..544fcbb 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -5,7 +5,7 @@ int main() { // VECTOR -// tests_vector_constructor(); + tests_vector_constructor(); // tests_vector_operator_assignation(); // tests_vector_begin(); // tests_vector_end(); @@ -34,7 +34,7 @@ int main() { // tests_vector_reverse_iterators(); // MAP -// tests_map_simple(); + tests_map_simple(); // tests_map_constructor(); // tests_map_operator_assignation(); // tests_map_begin(); diff --git a/tests/tests_definitions.cpp b/tests/tests_definitions.cpp index 6f278ea..511015c 100644 --- a/tests/tests_definitions.cpp +++ b/tests/tests_definitions.cpp @@ -4,23 +4,19 @@ // functions // ********************************************** -void add_to_list(std::string s, A_test* s1, A_test* s2, A_test* s3, A_test* s4) { +void add_to_list(std::string title, std::string type, A_test* test) { - std::vector test_sub_list; + std::vector test_sub_list; + std::vector< std::vector >::iterator it; - s1->title = s; - s2->title = s; - s3->title = s; - s4->title = s; - s1->type = "int"; - s2->type = "char"; - s3->type = "std::string"; - s4->type = "mystruct"; - test_sub_list.push_back(s1); - test_sub_list.push_back(s2); - test_sub_list.push_back(s3); - test_sub_list.push_back(s4); - test_list.push_back(test_sub_list); + // title != NULL for the first element + if (!title.empty()) + test_list.push_back(test_sub_list); + + test->title = title; + test->type = type; + it = test_list.end() - 1; + (*it).push_back(test); } void delete_structs() { diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index 7af511a..c096902 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -9,17 +9,18 @@ TEST(tests_map_simple) // title TITLE(simple test) - std::map first; - std::map::iterator it; + typename std::map first; + typename std::map::iterator it; - first['a']=10; - first['b']=30; - first['c']=50; - first['d']=70; + first[VAL('a')]=10; + first[VAL('b')]=30; + first[VAL('c')]=50; + first[VAL('d')]=70; for(it=first.begin(); it!=first.end(); ++it){ std::cout << it->first << " => " << it->second << '\n'; } + PRINT(first) DELETE } diff --git a/tests/tests_mystruct.cpp b/tests/tests_mystruct.cpp deleted file mode 100644 index 22f488d..0000000 --- a/tests/tests_mystruct.cpp +++ /dev/null @@ -1,19 +0,0 @@ - -#include "tests_mystruct.hpp" - -mystruct::mystruct(int data) - {_val = new int[2]; _val[0] = data; _val[1] = data;} - -mystruct::~mystruct() - {delete[] _val;} - -int * mystruct::get_data() const - {return _val;} - -std::ostream & operator<<(std::ostream & o, mystruct const * rhs) { - if (rhs != NULL) - o << (*rhs).get_data()[0] << "," << (*rhs).get_data()[1]; - else - o << "NULL"; - return (o); -} From 3074f7c93c10f0d80cf946055a38c5c90d6ff6b7 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sun, 19 Jun 2022 12:33:18 +0200 Subject: [PATCH 34/53] tests for map ope --- tests/includes/tests_utils.hpp | 16 +++++++++- tests/tests_map.cpp | 14 ++++----- tests/tests_vector.cpp | 54 +++++++++++++++++----------------- 3 files changed, 49 insertions(+), 35 deletions(-) diff --git a/tests/includes/tests_utils.hpp b/tests/includes/tests_utils.hpp index 7060d81..77aabb7 100644 --- a/tests/includes/tests_utils.hpp +++ b/tests/includes/tests_utils.hpp @@ -28,6 +28,8 @@ // **************************************** # define TITLE(s) std::cout << "\n" B_PURPLE #s RESET "\n\n"; # define VAL(n) val(n) +# define VALT(n) val(n) +# define VALU(n) val(n) # define TOI(n) toi(n) # define PRINT(n) print(n); # define DELETE delete_structs(); @@ -63,7 +65,7 @@ extern std::vector< mystruct* > mem_list; // adding each test to the list // *************************** -#define TEST(f_name) \ +#define TEST_V(f_name) \ template struct s_ ## f_name : public A_test\ { void func(); };\ void f_name () {\ @@ -75,6 +77,18 @@ extern std::vector< mystruct* > mem_list; template \ void s_ ## f_name ::func() +#define TEST_M(f_name) \ + template struct s_ ## f_name : public A_test\ + { void func(); };\ + void f_name () {\ + add_to_list(#f_name, "int, int", new(s_ ## f_name ));\ + add_to_list("", "char, int", new(s_ ## f_name ));\ + add_to_list("", "std::string, int", new(s_ ## f_name ));\ + add_to_list("", "mystruct*, int", new(s_ ## f_name ));\ + }\ + template \ + void s_ ## f_name ::func() + // templates print // ***************************************** diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index c096902..6cfb0ee 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -4,18 +4,18 @@ #include "tests_utils.hpp" -TEST(tests_map_simple) +TEST_M(tests_map_simple) { // title TITLE(simple test) - typename std::map first; - typename std::map::iterator it; + typename std::map first; + typename std::map::iterator it; - first[VAL('a')]=10; - first[VAL('b')]=30; - first[VAL('c')]=50; - first[VAL('d')]=70; + first[VALT('a')]=VALU(10); + first[VALT('b')]=VALU(30); + first[VALT('c')]=VALU(50); + first[VALT('d')]=VALU(70); for(it=first.begin(); it!=first.end(); ++it){ std::cout << it->first << " => " << it->second << '\n'; diff --git a/tests/tests_vector.cpp b/tests/tests_vector.cpp index 6bc1f02..86a73d7 100644 --- a/tests/tests_vector.cpp +++ b/tests/tests_vector.cpp @@ -4,7 +4,7 @@ #include "tests_utils.hpp" -TEST(tests_vector_constructor) +TEST_V(tests_vector_constructor) { // title TITLE(cplusplus.com reference) @@ -24,7 +24,7 @@ TEST(tests_vector_constructor) DELETE } -TEST(tests_vector_operator_assignation) +TEST_V(tests_vector_operator_assignation) { // title TITLE(cplusplus.com reference) @@ -51,7 +51,7 @@ TEST(tests_vector_operator_assignation) DELETE } -TEST(tests_vector_begin) +TEST_V(tests_vector_begin) { // title TITLE(cplusplus.com reference :) @@ -65,7 +65,7 @@ TEST(tests_vector_begin) DELETE } -TEST(tests_vector_end) +TEST_V(tests_vector_end) { // title TITLE(cplusplus.com reference :) @@ -79,7 +79,7 @@ TEST(tests_vector_end) DELETE } -TEST(tests_vector_rbegin) +TEST_V(tests_vector_rbegin) { // title TITLE(cplusplus.com reference :) @@ -98,7 +98,7 @@ TEST(tests_vector_rbegin) DELETE } -TEST(tests_vector_rend) +TEST_V(tests_vector_rend) { // title TITLE(cplusplus.com reference :) @@ -117,7 +117,7 @@ TEST(tests_vector_rend) DELETE } -TEST(tests_vector_size) +TEST_V(tests_vector_size) { // title TITLE(cplusplus.com reference :) @@ -139,7 +139,7 @@ TEST(tests_vector_size) DELETE } -TEST(tests_vector_max_size) +TEST_V(tests_vector_max_size) { // title TITLE(cplusplus.com reference :) @@ -158,7 +158,7 @@ TEST(tests_vector_max_size) DELETE } -TEST(tests_vector_resize) +TEST_V(tests_vector_resize) { // title TITLE(cplusplus.com reference :) @@ -242,7 +242,7 @@ TEST(tests_vector_resize) DELETE } -TEST(tests_vector_capacity) +TEST_V(tests_vector_capacity) { // title TITLE(cplusplus.com reference :) @@ -259,7 +259,7 @@ TEST(tests_vector_capacity) DELETE } -TEST(tests_vector_empty) +TEST_V(tests_vector_empty) { // title TITLE(cplusplus.com reference :) @@ -280,7 +280,7 @@ TEST(tests_vector_empty) DELETE } -TEST(tests_vector_reserve) +TEST_V(tests_vector_reserve) { // title TITLE(cplusplus.com reference :) @@ -314,7 +314,7 @@ TEST(tests_vector_reserve) DELETE } -TEST(tests_vector_operator_access) +TEST_V(tests_vector_operator_access) { // title TITLE(cplusplus.com reference :) @@ -340,7 +340,7 @@ TEST(tests_vector_operator_access) DELETE } -TEST(tests_vector_at) +TEST_V(tests_vector_at) { // title TITLE(cplusplus.com reference :) @@ -357,7 +357,7 @@ TEST(tests_vector_at) DELETE } -TEST(tests_vector_front) +TEST_V(tests_vector_front) { // title TITLE(cplusplus.com reference :) @@ -378,7 +378,7 @@ TEST(tests_vector_front) DELETE } -TEST(tests_vector_back) +TEST_V(tests_vector_back) { // title TITLE(cplusplus.com reference :) @@ -397,7 +397,7 @@ TEST(tests_vector_back) DELETE } -TEST(tests_vector_assign) +TEST_V(tests_vector_assign) { // title TITLE(cplusplus.com reference :) @@ -466,7 +466,7 @@ TEST(tests_vector_assign) DELETE } -TEST(tests_vector_push_back) +TEST_V(tests_vector_push_back) { // title TITLE(cplusplus.com reference :) @@ -498,7 +498,7 @@ TEST(tests_vector_push_back) DELETE } -TEST(tests_vector_pop_back) +TEST_V(tests_vector_pop_back) { // title TITLE(cplusplus.com reference :) @@ -529,7 +529,7 @@ TEST(tests_vector_pop_back) DELETE } -TEST(tests_vector_insert) +TEST_V(tests_vector_insert) { typename ft::vector::iterator it; @@ -615,7 +615,7 @@ TEST(tests_vector_insert) DELETE } -TEST(tests_vector_erase) +TEST_V(tests_vector_erase) { // title TITLE(cplusplus.com reference :) @@ -656,7 +656,7 @@ TEST(tests_vector_erase) DELETE } -TEST(tests_vector_swap) +TEST_V(tests_vector_swap) { // title TITLE(cplusplus.com reference :) @@ -675,7 +675,7 @@ TEST(tests_vector_swap) DELETE } -TEST(tests_vector_clear) +TEST_V(tests_vector_clear) { // title TITLE(cplusplus.com reference :) @@ -698,7 +698,7 @@ TEST(tests_vector_clear) DELETE } -TEST(tests_vector_get_allocator) +TEST_V(tests_vector_get_allocator) { // title TITLE(cplusplus.com reference :) @@ -724,7 +724,7 @@ TEST(tests_vector_get_allocator) DELETE } -TEST(tests_vector_relational_operators) +TEST_V(tests_vector_relational_operators) { // title TITLE(cplusplus.com reference :) @@ -742,7 +742,7 @@ TEST(tests_vector_relational_operators) DELETE } -TEST(tests_vector_swap_non_member) +TEST_V(tests_vector_swap_non_member) { // title TITLE(cplusplus.com reference :) @@ -761,7 +761,7 @@ TEST(tests_vector_swap_non_member) DELETE } -TEST(tests_vector_reverse_iterators) +TEST_V(tests_vector_reverse_iterators) { // title TITLE(cplusplus.com reference) From 8a404b08398702e72e2cabd2e76c8f3ca7961d6f Mon Sep 17 00:00:00 2001 From: hugogogo Date: Sun, 19 Jun 2022 12:36:01 +0200 Subject: [PATCH 35/53] little correction on macro for map tests --- tests/tests_map.cpp | 49 +++++++++++++++++++++------------------------ 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index 6cfb0ee..2f440ae 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -10,23 +10,20 @@ TEST_M(tests_map_simple) TITLE(simple test) typename std::map first; - typename std::map::iterator it; + typename std::map::iterator it; first[VALT('a')]=VALU(10); first[VALT('b')]=VALU(30); first[VALT('c')]=VALU(50); first[VALT('d')]=VALU(70); - for(it=first.begin(); it!=first.end(); ++it){ - std::cout << it->first << " => " << it->second << '\n'; - } PRINT(first) DELETE } /* -TEST(tests_map_constructor) +TEST_M(tests_map_constructor) { // title TITLE(cplusplus.com reference) @@ -57,7 +54,7 @@ TEST(tests_map_constructor) DELETE } -TEST(tests_map_operator_assignation) +TEST_M(tests_map_operator_assignation) { // title TITLE(cplusplus.com reference) @@ -78,7 +75,7 @@ TEST(tests_map_operator_assignation) DELETE } -TEST(tests_map_begin) +TEST_M(tests_map_begin) { // title TITLE(cplusplus.com reference) @@ -96,7 +93,7 @@ TEST(tests_map_begin) DELETE } -TEST(tests_map_end) +TEST_M(tests_map_end) { // title TITLE(cplusplus.com reference) @@ -114,7 +111,7 @@ TEST(tests_map_end) DELETE } -TEST(tests_map_rbegin) +TEST_M(tests_map_rbegin) { // title TITLE(cplusplus.com reference) @@ -133,7 +130,7 @@ TEST(tests_map_rbegin) DELETE } -TEST(tests_map_rend) +TEST_M(tests_map_rend) { // title TITLE(cplusplus.com reference) @@ -152,7 +149,7 @@ TEST(tests_map_rend) DELETE } -TEST(tests_map_empty) +TEST_M(tests_map_empty) { // title TITLE(cplusplus.com reference) @@ -172,7 +169,7 @@ TEST(tests_map_empty) DELETE } -TEST(tests_map_size) +TEST_M(tests_map_size) { // title TITLE(cplusplus.com reference) @@ -187,7 +184,7 @@ TEST(tests_map_size) DELETE } -TEST(tests_map_max_size) +TEST_M(tests_map_max_size) { // title TITLE(cplusplus.com reference) @@ -205,7 +202,7 @@ TEST(tests_map_max_size) DELETE } -TEST(tests_map_operator_access) +TEST_M(tests_map_operator_access) { // title TITLE(cplusplus.com reference) @@ -226,7 +223,7 @@ TEST(tests_map_operator_access) DELETE } -TEST(tests_map_insert) +TEST_M(tests_map_insert) { // title TITLE(cplusplus.com reference) @@ -265,7 +262,7 @@ TEST(tests_map_insert) DELETE } -TEST(tests_map_erase) +TEST_M(tests_map_erase) { // title TITLE(cplusplus.com reference) @@ -296,7 +293,7 @@ TEST(tests_map_erase) DELETE } -TEST(tests_map_swap) +TEST_M(tests_map_swap) { // title TITLE(cplusplus.com reference) @@ -323,7 +320,7 @@ TEST(tests_map_swap) DELETE } -TEST(tests_map_clear) +TEST_M(tests_map_clear) { // title TITLE(cplusplus.com reference) @@ -349,7 +346,7 @@ TEST(tests_map_clear) DELETE } -TEST(tests_map_key_comp) +TEST_M(tests_map_key_comp) { // title TITLE(cplusplus.com reference) @@ -376,7 +373,7 @@ TEST(tests_map_key_comp) DELETE } -TEST(tests_map_value_comp) +TEST_M(tests_map_value_comp) { // title TITLE(cplusplus.com reference) @@ -399,7 +396,7 @@ TEST(tests_map_value_comp) DELETE } -TEST(tests_map_find) +TEST_M(tests_map_find) { // title TITLE(cplusplus.com reference) @@ -425,7 +422,7 @@ TEST(tests_map_find) DELETE } -TEST(tests_map_count) +TEST_M(tests_map_count) { // title TITLE(cplusplus.com reference) @@ -449,7 +446,7 @@ TEST(tests_map_count) DELETE } -TEST(tests_map_lower_bound) +TEST_M(tests_map_lower_bound) { // title TITLE(cplusplus.com reference) @@ -475,7 +472,7 @@ TEST(tests_map_lower_bound) DELETE } -TEST(tests_map_upper_bound) +TEST_M(tests_map_upper_bound) { // title TITLE(cplusplus.com reference) @@ -501,7 +498,7 @@ TEST(tests_map_upper_bound) DELETE } -TEST(tests_map_equal_range) +TEST_M(tests_map_equal_range) { // title TITLE(cplusplus.com reference) @@ -524,7 +521,7 @@ TEST(tests_map_equal_range) DELETE } -TEST(tests_map_get_allocator) +TEST_M(tests_map_get_allocator) { // title TITLE(cplusplus.com reference) From 8c181b6407bcafaa6a35478bf65561267046d3ff Mon Sep 17 00:00:00 2001 From: hugogogo Date: Mon, 20 Jun 2022 15:40:35 +0200 Subject: [PATCH 36/53] map pair ok --- Makefile | 6 +- headers/map.hpp | 118 ++++++++++++++++++++++----------- headers/pair.hpp | 89 +++++++++++++++++++++++++ templates/map.tpp | 45 ++++++++++--- tests/includes/tests_utils.hpp | 12 ++-- tests/main.cpp | 4 +- tests/tests_map.cpp | 80 +++++++++++++++++++--- 7 files changed, 287 insertions(+), 67 deletions(-) create mode 100644 headers/pair.hpp diff --git a/Makefile b/Makefile index 4892a68..ba89a80 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ RESET = "\e[0m" NAME = containers -CC = g++ +CC = clang++ EXT = cpp CFLAGS = -Wall -Wextra -Werror $(INCLUDES) @@ -66,11 +66,13 @@ HEADERS = colors.h \ reverse_iterator.hpp \ equal.hpp \ lexicographical_compare.hpp \ + pair.hpp \ \ vector.hpp D_TEMPLATES = ./templates -TEMPLATES = vector.tpp +TEMPLATES = vector.tpp \ + map.tpp D_TESTS = ./tests/includes TESTS = main.hpp \ diff --git a/headers/map.hpp b/headers/map.hpp index 80001fc..b2625c1 100644 --- a/headers/map.hpp +++ b/headers/map.hpp @@ -2,52 +2,68 @@ #ifndef MAP_HPP # define MAP_HPP -//# include "colors.h" -//# include -//# include -//# include // std::allocator -//# include // std::min, std::max -//# include // out_of_range, length_error, logic_error -//# include // NULL, std::size_t, std::ptrdiff_t -// -//# include "enable_if.hpp" -//# include "is_integral.hpp" -//# include "reverse_iterator.hpp" -//# include "equal.hpp" -//# include "lexicographical_compare.hpp" +# include "colors.h" +# include // std::allocator +# include // NULL, std::size_t, std::ptrdiff_t +# include // std::less, std::binary_function + +# include "pair.hpp" +//# include "bst.hpp" namespace ft { -//template < -// class T, -// class Allocator = std::allocator > -class map { +template < + class Key, // map::key_type + class T, // map::mapped_type + class Compare = std::less, // map::key_compare + class Alloc = std::allocator< ft::pair > // map::allocator_type +> class map { public: -// typedef T value_type; -// typedef Allocator allocator_type; -// typedef std::size_t size_type; -// typedef std::ptrdiff_t difference_type; -// -// typedef T * iterator; -// typedef T const * const_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 Key key_type; + typedef T mapped_type; + typedef pair value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef Compare key_compare; + typedef Alloc allocator_type; +// typedef typename allocator_type::reference reference; +// typedef typename allocator_type::const_reference const_reference; +// typedef typename allocator_type::pointer pointer; +// typedef typename allocator_type::const_pointer const_pointer; + +// typedef Bst bst_map; + +// typedef typename bst_map::iterator iterator; +// typedef typename bst_map::const_iterator const_iterator; +// typedef typename bst_map::reverse_iterator reverse_iterator; +// typedef typename bst_map::const_reverse_iterator const_reverse_iterator; + + + /**************** + * member class : + ****************/ +// // https://en.cppreference.com/w/cpp/container/map/value_compare +// class value_compare : public std::binary_function +// { +// friend class map; +// protected: +// Compare comp; +// value_compare(Compare c) : comp(c) {} +// public: +// bool operator() (const value_type& x, const value_type& y) const +// { return comp(x.first, y.first); } +// }; /************ * copliens : ************/ //// constructors ------------------------------ -// explicit map (const key_compare& comp = key_compare(), -// const allocator_type& alloc = allocator_type()); + explicit map (const key_compare& comp = key_compare(), + const allocator_type& alloc = allocator_type()); // template // map (InputIterator first, InputIterator last, // const key_compare& comp = key_compare(), @@ -148,16 +164,38 @@ public: private: -// size_type _size; -// size_type _capacity; -// value_type * _mem_ptr; -// allocator_type _allocator; -// -// void _destroy(iterator first, iterator last); -// void _increment_capacity(size_type n); + allocator_type _allocator; + key_compare _comp; }; + + /************************ + * non-member functions : + ************************/ +//// operator == ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator== +// ( const std::map& lhs, const std::map& rhs ); +//// operator != ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator!= +// ( const std::map& lhs, const std::map& rhs ); +//// operator < -------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator< +// ( const std::map& lhs, const std::map& rhs ); +//// operator <= ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator<= +// ( const std::map& lhs, const std::map& rhs ); +//// operator > -------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator> +// ( const std::map& lhs, const std::map& rhs ); +//// operator >= ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator>= +// ( const std::map& lhs, const std::map& rhs ); +//// swap (map) ----------------------------- +//template< class Key, class T, class Compare, class Alloc > void swap +// ( std::map& lhs, std::map& rhs ); + + } // namespace ft # include "map.tpp" diff --git a/headers/pair.hpp b/headers/pair.hpp new file mode 100644 index 0000000..d246eb5 --- /dev/null +++ b/headers/pair.hpp @@ -0,0 +1,89 @@ +#ifndef PAIR_HPP +# define PAIR_HPP + +# define PR_TPL template < class T1, class T2 > +# define PR pair + +namespace ft { + +PR_TPL + struct pair { + + typedef T1 first_type; + typedef T2 second_type; + + pair(); + template< typename U, typename V > + pair(const pair& pr); + pair(const first_type& a, const second_type& b); + + T1 first; + T2 second; +}; + + + /************ + * copliens : + ************/ +PR_TPL PR:: + pair() { +} +PR_TPL template< typename U, typename V > PR:: + pair(const pair& pr) : first(pr.first), second(pr.second) { +} +PR_TPL PR:: + pair(const first_type& a, const second_type& b) : first(a), second(b) { +} + + + + /************************ + * non-member functions : + ************************/ +PR_TPL + bool operator==(const PR& lhs, const PR& rhs) { + + return (lhs.first == rhs.first) && (lhs.second == rhs.second); +} +PR_TPL + bool operator<(const PR& lhs, const PR& rhs) { + + return ( + lhs.first < rhs.first + || ( !(rhs.first < lhs.first) && (lhs.second < rhs.second) ) + ); +} +PR_TPL + bool operator!=(const PR& lhs, const PR& rhs) { + + return !(lhs == rhs); +} +PR_TPL + bool operator>(const PR& lhs, const PR& rhs) { + + return (rhs < lhs); +} +PR_TPL + bool operator<=(const PR& lhs, const PR& rhs) { + + return !(lhs > rhs); +} + +PR_TPL + bool operator>=(const PR& lhs, const PR& rhs) { + + return !(lhs < rhs); +} +PR_TPL + PR make_pair(T1 x, T2 y) { + + return PR(x, y) ; +} + +} // namespace ft + +# undef PR +# undef PR_TPL + +#endif + diff --git a/templates/map.tpp b/templates/map.tpp index e0a451d..c584390 100644 --- a/templates/map.tpp +++ b/templates/map.tpp @@ -1,9 +1,7 @@ -//#define VT_TPL template -//#define VT vector -//#define MP_TPL template < typename Key, typename T, typename Compare, typename Allocator > -//#define MP map +#define MP_TPL template < typename Key, typename T, typename Compare, typename Alloc > +#define MP map namespace ft { @@ -13,8 +11,13 @@ namespace ft { * copliens : ************/ //// constructors ------------------------------ -// explicit map (const key_compare& comp = key_compare(), -// const allocator_type& alloc = allocator_type()); +MP_TPL MP:: + map (const key_compare & comp, const allocator_type & alloc) + : _allocator(alloc) + , _comp(comp) { + + return; +} // template // map (InputIterator first, InputIterator last, // const key_compare& comp = key_compare(), @@ -113,8 +116,34 @@ namespace ft { //// get_allocator ----------------------------- // allocator_type get_allocator() const; + + /************************ + * non-member functions : + ************************/ +//// operator == ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator== +// ( const std::map& lhs, const std::map& rhs ); +//// operator != ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator!= +// ( const std::map& lhs, const std::map& rhs ); +//// operator < -------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator< +// ( const std::map& lhs, const std::map& rhs ); +//// operator <= ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator<= +// ( const std::map& lhs, const std::map& rhs ); +//// operator > -------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator> +// ( const std::map& lhs, const std::map& rhs ); +//// operator >= ------------------------------- +//template< class K, class T, class Comp, class Alloc > bool operator>= +// ( const std::map& lhs, const std::map& rhs ); +//// swap (map) ----------------------------- +//template< class Key, class T, class Compare, class Alloc > void swap +// ( std::map& lhs, std::map& rhs ); + } // namespace ft -//#undef VT -//#undef VT_TPL +#undef VT +#undef VT_TPL diff --git a/tests/includes/tests_utils.hpp b/tests/includes/tests_utils.hpp index 77aabb7..170c866 100644 --- a/tests/includes/tests_utils.hpp +++ b/tests/includes/tests_utils.hpp @@ -20,6 +20,7 @@ namespace ft = std; #else #include "vector.hpp" + #include "map.hpp" #include "reverse_iterator.hpp" #endif @@ -82,9 +83,6 @@ extern std::vector< mystruct* > mem_list; { void func(); };\ void f_name () {\ add_to_list(#f_name, "int, int", new(s_ ## f_name ));\ - add_to_list("", "char, int", new(s_ ## f_name ));\ - add_to_list("", "std::string, int", new(s_ ## f_name ));\ - add_to_list("", "mystruct*, int", new(s_ ## f_name ));\ }\ template \ void s_ ## f_name ::func() @@ -104,15 +102,15 @@ template std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; } template - void print(ft::map ma) { + void print(ft::map mp) { int i = 0; typename ft::map::iterator it; - typename ft::map::iterator it_end = ma.end(); + typename ft::map::iterator it_end = mp.end(); - for (it = ma.begin(); it != it_end; ++it, i++) + for (it = mp.begin(); it != it_end; ++it, i++) std::cout << "[" << i << "]" << it->first << ":" << it->second << " "; - std::cout << "\nsize:" << ma.size() << "\n"; + std::cout << "\nsize:" << mp.size() << "\n"; } // templates get value diff --git a/tests/main.cpp b/tests/main.cpp index 544fcbb..17a98e1 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -5,7 +5,7 @@ int main() { // VECTOR - tests_vector_constructor(); +// tests_vector_constructor(); // tests_vector_operator_assignation(); // tests_vector_begin(); // tests_vector_end(); @@ -57,6 +57,8 @@ int main() { // tests_map_upper_bound(); // tests_map_equal_range(); // tests_map_get_allocator(); +// tests_map_relational_operators(); +// tests_map_swap_non_member(); // STACK diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index 2f440ae..d257f0f 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -9,15 +9,12 @@ TEST_M(tests_map_simple) // title TITLE(simple test) - typename std::map first; - typename std::map::iterator it; - - first[VALT('a')]=VALU(10); - first[VALT('b')]=VALU(30); - first[VALT('c')]=VALU(50); - first[VALT('d')]=VALU(70); - - PRINT(first) + typename ft::map mp; +// typename std::map::iterator it; +// +// mp[VALT('a')] = VALU(10); +// +// PRINT(mp) DELETE } @@ -543,6 +540,71 @@ TEST_M(tests_map_get_allocator) DELETE } +TEST_M(tests_map_relational_operators) +{ + // title + TITLE(cplusplus.com reference) + + std::map alice{{1, 'a'}, {2, 'b'}, {3, 'c'}}; + std::map bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}}; + std::map eve{{1, 'a'}, {2, 'b'}, {3, 'c'}}; + + std::cout << std::boolalpha; + + // Compare non equal containers + std::cout << "alice == bob returns " << (alice == bob) << '\n'; + std::cout << "alice != bob returns " << (alice != bob) << '\n'; + std::cout << "alice < bob returns " << (alice < bob) << '\n'; + std::cout << "alice <= bob returns " << (alice <= bob) << '\n'; + std::cout << "alice > bob returns " << (alice > bob) << '\n'; + std::cout << "alice >= bob returns " << (alice >= bob) << '\n'; + + std::cout << '\n'; + + // Compare equal containers + std::cout << "alice == eve returns " << (alice == eve) << '\n'; + std::cout << "alice != eve returns " << (alice != eve) << '\n'; + std::cout << "alice < eve returns " << (alice < eve) << '\n'; + std::cout << "alice <= eve returns " << (alice <= eve) << '\n'; + std::cout << "alice > eve returns " << (alice > eve) << '\n'; + std::cout << "alice >= eve returns " << (alice >= eve) << '\n'; + + DELETE +} + + +TEST_M(tests_map_swap_non_member) +{ + // title + TITLE(cplusplus.com reference) + + std::map alice{{1, 'a'}, {2, 'b'}, {3, 'c'}}; + std::map bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}}; + + auto print = [](std::pair& n) { + std::cout << " " << n.first << '(' << n.second << ')'; + }; + + // Print state before swap + std::cout << "alice:"; + std::for_each(alice.begin(), alice.end(), print); + std::cout << "\n" "bob :"; + std::for_each(bob.begin(), bob.end(), print); + std::cout << '\n'; + + std::cout << "-- SWAP\n"; + std::swap(alice, bob); + + // Print state after swap + std::cout << "alice:"; + std::for_each(alice.begin(), alice.end(), print); + std::cout << "\n" "bob :"; + std::for_each(bob.begin(), bob.end(), print); + std::cout << '\n'; + + DELETE +} + */ #endif From c7114c1db277c51c7b530edffbf8860c242a07f6 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Mon, 20 Jun 2022 19:05:52 +0200 Subject: [PATCH 37/53] using functionning luke bst --- Makefile | 12 +- headers/bst.hpp | 148 +++++++++ headers/bst_iterator.hpp | 207 +++++++++++++ headers/bst_node.hpp | 50 ++++ headers/map.hpp | 7 +- templates/bst.tpp | 628 +++++++++++++++++++++++++++++++++++++++ templates/map.tpp | 6 +- tests/tests_map.cpp | 9 +- 8 files changed, 1056 insertions(+), 11 deletions(-) create mode 100644 headers/bst.hpp create mode 100644 headers/bst_iterator.hpp create mode 100644 headers/bst_node.hpp create mode 100644 templates/bst.tpp diff --git a/Makefile b/Makefile index ba89a80..27780ad 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ RESET = "\e[0m" NAME = containers -CC = clang++ +CC = g++ EXT = cpp CFLAGS = -Wall -Wextra -Werror $(INCLUDES) @@ -67,11 +67,17 @@ HEADERS = colors.h \ equal.hpp \ lexicographical_compare.hpp \ pair.hpp \ + bst.hpp \ + bst_node.hpp \ + bst_iterator.hpp \ \ - vector.hpp + vector.hpp \ + map.hpp D_TEMPLATES = ./templates -TEMPLATES = vector.tpp \ +TEMPLATES = bst.tpp \ + \ + vector.tpp \ map.tpp D_TESTS = ./tests/includes diff --git a/headers/bst.hpp b/headers/bst.hpp new file mode 100644 index 0000000..f7dab8c --- /dev/null +++ b/headers/bst.hpp @@ -0,0 +1,148 @@ +#ifndef BST_HPP +# define BST_HPP + +# include // std::allocator +# include // NULL, size_t, ptrdiff_t +# include // max() +# include // std::less() + +# include "reverse_iterator.hpp" +# include "equal.hpp" +# include "lexicographical_compare.hpp" + +# include "pair.hpp" +# include "bst_node.hpp" +# include "bst_iterator.hpp" + +namespace ft { + +template < + typename Key, + typename T, + typename Compare = std::less, + typename Allocator = std::allocator< ft::pair > +> class Bst +{ + public: + typedef Key key_type; + typedef T mapped_type; + typedef pair value_type; + typedef Compare key_compare; + typedef Allocator allocator_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef typename Allocator::pointer pointer; + typedef typename Allocator::const_pointer const_pointer; + typedef typename Allocator::reference reference; + typedef typename Allocator::const_reference const_reference; + + + typedef Bst_iterator iterator; + typedef Bst_const_iterator const_iterator; + typedef ft::reverse_iterator reverse_iterator; + typedef ft::reverse_iterator const_reverse_iterator; + + + // Member functions + explicit Bst(const Compare& comp = Compare(), const Allocator& alloc = Allocator() ); + template < typename InputIt > + Bst(InputIt first, InputIt last, const Compare& comp = Compare(), const Allocator& alloc = Allocator()); + Bst(const Bst& src); + ~Bst(); + + Bst& operator=(const Bst& rhs); + + // Element access + T& operator[](const Key& key); + + // Iterators + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + + // Capacity + bool empty() const; + size_type size() const; + size_type max_size() const; + + // Modifiers + void clear(); + pair insert(const value_type& value); + iterator insert(iterator hint, const value_type& value); + template < typename InputIt > + void insert(InputIt first, InputIt last); + void erase(iterator pos); + void erase(iterator first, iterator last); + size_type erase(const Key& key); + void swap(Bst& other); + + // Lookup + iterator find(const Key& key); + const_iterator find(const Key& key) const; + size_type count(const Key& key) const; + + private: + size_type _size; + node* _root; + node_sentinel* _sentinel; + Compare _comp; + Allocator _allocator; + + // TODO : rebind syntaxe pas clair. + typename Allocator::template rebind< node >::other _allocator_node; // Peu clair, verifier syntaxe + typename Allocator::template rebind< node_sentinel >::other _allocator_node_sentinel; // Peu clair, verifier syntaxe + + void _init_sentinel(); + pair _insert(const value_type& value); + node* _erase(iterator pos); + node* _subtree_shift(node* st_old, node* st_new); + + // AVL Balancing + void _insert_rebalancing(node* n); + void _erase_rebalancing(node* n); + + short _compute_height(node* n); + short _bf(node* n); // balance factor + node* _rotate_left(node* n); + node* _rotate_right(node* n); + }; + + // Non-member functions + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator==(const Bst& lhs, const Bst& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator!=(const Bst& lhs, const Bst& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator<(const Bst& lhs, const Bst& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator>(const Bst& lhs, const Bst& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator<=(const Bst& lhs, const Bst& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator>=(const Bst& lhs, const Bst& rhs); + + template < typename Key, typename T, typename Compare, typename Alloc > + void swap(Bst& lhs, Bst& rhs); + +} // namespace ft + +# include "bst.tpp" + +// https://en.wikipedia.org/wiki/Binary_search_tree +// https://en.wikipedia.org/wiki/AVL_tree + +// https://fr.wikipedia.org/wiki/Arbre_binaire_de_recherche +// https://fr.wikipedia.org/wiki/Arbre_AVL + +// https://visualgo.net/en/bst +// https://visualgo.net/en/bst?slide=14-8 // --> to 14-13 + + +#endif + diff --git a/headers/bst_iterator.hpp b/headers/bst_iterator.hpp new file mode 100644 index 0000000..077f601 --- /dev/null +++ b/headers/bst_iterator.hpp @@ -0,0 +1,207 @@ +#ifndef BST_ITERATOR_HPP +# define BST_ITERATOR_HPP + +# include // NULL, ptrdiff_t +# include // iterator_tag + +# include "pair.hpp" +# include "bst_node.hpp" + +namespace ft { + +template < + typename Key, + typename T, + typename Compare, + typename Allocator +> class Bst_iterator +{ + private: + typedef Bst_iterator Self; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef pair value_type; + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; + + Bst_iterator() : _node(), _sentinel() {} + Bst_iterator(node* n, node_sentinel* sentinel) : _node(n), _sentinel(sentinel) {} + //Bst_iterator(const Bst_iterator& src) : _node(src._node), _sentinel(src._sentinel) {} //implicit + + reference operator*() const + { return _node->value; } + pointer operator->() const + { return &_node->value; } + + Self& operator++() + { + if (_node == NULL) + _node = _sentinel->child->min(); + else if (_node->right) + _node = _node->right->min(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->right) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self& operator--() + { + if (_node == NULL) + _node = _sentinel->child->max(); + else if (_node->left) + _node = _node->left->max(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->left) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self operator++(int) + { + //Self old(*this); + Self old = *this; + ++(*this); + return old; + } + + Self operator--(int) + { + //Self old(*this); + Self old = *this; + --(*this); + return old; + } + + node* getNode() + { return _node; } + const node* getNode() const + { return _node; } + const node_sentinel* getSentinel() const + { return _sentinel; } + + // TODO : friend Non-member functions syntaxe pas clair. + friend bool operator==(const Self &lhs, const Self &rhs) + { return lhs._node == rhs._node; } + friend bool operator!=(const Self &lhs, const Self &rhs) + { return !(lhs._node == rhs._node); } + + private: + node* _node; + node_sentinel* _sentinel; +}; + +template < + typename Key, + typename T, + typename Compare, + typename Allocator +> class Bst_const_iterator +{ + private: + typedef Bst_const_iterator Self; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef pair value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + + Bst_const_iterator() : _node(), _sentinel() {} + Bst_const_iterator(const node* node, const node_sentinel* sentinel) : _node(node), _sentinel(sentinel) {} + //Bst_const_iterator(const Bst_const_iterator& src) : _node(src._node), _sentinel(src._sentinel) {} //implicit + Bst_const_iterator(const Bst_iterator& src) : _node(src.getNode()), _sentinel(src.getSentinel()) {} + + reference operator*() const + { return _node->value; } + pointer operator->() const + { return &_node->value; } + + Self& operator++() + { + if (_node == NULL) + _node = _sentinel->child->min(); + else if (_node->right) + _node = _node->right->min(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->right) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self& operator--() + { + if (_node == NULL) + _node = _sentinel->child->max(); + else if (_node->left) + _node = _node->left->max(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->left) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self operator++(int) + { + //Self old(*this); + Self old = *this; + ++(*this); + return old; + } + + Self operator--(int) + { + //Self old(*this); + Self old = *this; + --(*this); + return old; + } + + node* getNode() const + { return _node; } + + friend bool operator==(const Self &lhs, const Self &rhs) + { return lhs._node == rhs._node; } + friend bool operator!=(const Self &lhs, const Self &rhs) + { return !(lhs._node == rhs._node); } + + private: + const node* _node; + const node_sentinel* _sentinel; +}; + +} // namespace ft + +#endif + diff --git a/headers/bst_node.hpp b/headers/bst_node.hpp new file mode 100644 index 0000000..2fa8ca1 --- /dev/null +++ b/headers/bst_node.hpp @@ -0,0 +1,50 @@ + +#ifndef BST_NODE_HPP +# define BST_NODE_HPP + +# include // NULL + +namespace ft { + +template < typename ValueType > +struct node +{ + ValueType value; + node *up; + node *left; + node *right; + short height; + + node(const ValueType& val) : value(val), up(NULL), left(NULL), right(NULL), height(1) {} + + node* min() + { + node* n = this; + + while (n->left) + n = n->left; + return n; + } + + node* max() + { + node* n = this; + + while (n->right) + n = n->right; + return n; + } +}; + +template < typename ValueType > +struct node_sentinel +{ + node *child; + + node_sentinel() : child(NULL) {} +}; + +} // namespace ft + +#endif + diff --git a/headers/map.hpp b/headers/map.hpp index b2625c1..c00ade3 100644 --- a/headers/map.hpp +++ b/headers/map.hpp @@ -8,7 +8,7 @@ # include // std::less, std::binary_function # include "pair.hpp" -//# include "bst.hpp" +# include "bst.hpp" namespace ft { @@ -34,7 +34,7 @@ public: // typedef typename allocator_type::pointer pointer; // typedef typename allocator_type::const_pointer const_pointer; -// typedef Bst bst_map; + typedef Bst bst_map; // typedef typename bst_map::iterator iterator; // typedef typename bst_map::const_iterator const_iterator; @@ -107,7 +107,7 @@ public: * element access : ******************/ //// operator[] -------------------------------- -// mapped_type & operator[] (const key_type& k); + mapped_type & operator[] (const key_type& k); /************* @@ -166,6 +166,7 @@ private: allocator_type _allocator; key_compare _comp; + bst_map _bst; }; diff --git a/templates/bst.tpp b/templates/bst.tpp new file mode 100644 index 0000000..0ade6c0 --- /dev/null +++ b/templates/bst.tpp @@ -0,0 +1,628 @@ + +#define BST_TEMPLATE template < typename Key, typename T, typename Compare, typename Allocator > +#define BST Bst + +namespace ft { + + + ////////////////////// + // Member functions // + +BST_TEMPLATE +BST:: + Bst(const Compare& comp, const Allocator& alloc) : +_size(0), +_root(NULL), +_comp(comp), +_allocator(alloc) +{ + _init_sentinel(); +} + +BST_TEMPLATE +template < typename InputIt > +BST:: + Bst(InputIt first, InputIt last, const Compare& comp, const Allocator& alloc) : +_size(0), +_root(NULL), +_comp(comp), +_allocator(alloc) +{ + _init_sentinel(); + insert(first, last); +} + +BST_TEMPLATE +BST:: + Bst(const Bst& src) : +_size(0), +_root(NULL), +_comp(src._comp), +_allocator(src._allocator) +{ + _init_sentinel(); + *this = src; +} + +BST_TEMPLATE +BST:: + ~Bst() +{ + clear(); + _allocator_node_sentinel.destroy(_sentinel); + _allocator_node_sentinel.deallocate(_sentinel, 1); +} + +BST_TEMPLATE +BST& BST:: + operator=(const Bst& rhs) +{ + if (this == &rhs) + return (*this); + Bst new_bst(rhs.begin(), rhs.end()); + swap(new_bst); + return (*this); +} + + + //////////////////// + // Element access // + +BST_TEMPLATE +T& BST:: + operator[](const Key& key) +{ + node* n = _root; + //node* prev = NULL; + + while (n) + { + //prev = n; + if (_comp(key, n->value.first)) + n = n->left; + else if (_comp(n->value.first, key)) + n = n->right; + else + return (n->value.second); + } + + // TODO : Call insert with hint (prev) + n = insert( ft::make_pair(key, mapped_type()) ).first.getNode(); + + return (n->value.second); +} + + + /////////////// + // Iterators // + +BST_TEMPLATE +typename BST::iterator BST:: + begin() +{ + if (_root) + return iterator(_root->min(), _sentinel); + else + return end(); +} + +BST_TEMPLATE +typename BST::const_iterator BST:: + begin() const +{ + if (_root) + return const_iterator(_root->min(), _sentinel); + else + return end(); +} + +BST_TEMPLATE +typename BST::iterator BST:: + end() { return iterator(NULL, _sentinel); } + +BST_TEMPLATE +typename BST::const_iterator BST:: + end() const { return const_iterator(NULL, _sentinel); } + +BST_TEMPLATE +typename BST::reverse_iterator BST:: + rbegin() { return reverse_iterator(end()); } + +BST_TEMPLATE +typename BST::const_reverse_iterator BST:: + rbegin() const { return const_reverse_iterator(end()); } + +BST_TEMPLATE +typename BST::reverse_iterator BST:: + rend() { return reverse_iterator(begin()); } + +BST_TEMPLATE +typename BST::const_reverse_iterator BST:: + rend() const { return const_reverse_iterator(begin()); } + + + ////////////// + // Capacity // + +BST_TEMPLATE +bool BST:: + empty() const { return (_size == 0); } + +BST_TEMPLATE +typename BST::size_type BST:: + size() const { return (_size); } + +BST_TEMPLATE +typename BST::size_type BST:: + max_size() const +{ + return ( _allocator_node.max_size() ); +} + + + /////////////// + // Modifiers // + +BST_TEMPLATE +void BST:: + clear() +{ + // TODO : optimisation jouable ? + erase(begin(), end()); + //_size = 0; +} + +BST_TEMPLATE +pair BST:: + insert(const value_type& value) +{ + pair ret; + + ret = _insert(value); + if (ret.second == true) + _insert_rebalancing(ret.first.getNode()->up); + return (ret); +} + +BST_TEMPLATE +typename BST::iterator BST:: + insert(iterator hint, const value_type& value) +{ + // TODO : optimise with hint + (void)hint; + return insert(value).first; +} + +BST_TEMPLATE +template < typename InputIt > +void BST:: + insert(InputIt first, InputIt last) +{ + //static int i = 0; // Debug + while (first != last) + { + insert(*first); + ++first; + //std::cout << "c|" << i << "\n"; + //++i; + } +} + +BST_TEMPLATE +void BST:: + erase(iterator pos) +{ + node* delete_point; + delete_point = _erase(pos); + _erase_rebalancing(delete_point); +} + +BST_TEMPLATE +void BST:: + erase(iterator first, iterator last) +{ + while (first != last) + erase(first++); +} + +BST_TEMPLATE +typename BST::size_type BST:: + erase(const Key& key) +{ + iterator pos = find(key); + if (pos == end()) + return (0); + else + { + erase(pos); + return (1); + } +} + +BST_TEMPLATE +void BST:: + swap(Bst& other) +{ + node* tmp_root = _root; + node_sentinel* tmp_sentinel = _sentinel; + size_type tmp_size = _size; + + _root = other._root; + _sentinel = other._sentinel; + _size = other._size; + + other._root = tmp_root; + other._sentinel = tmp_sentinel; + other._size = tmp_size; +} + + + //////////// + // Lookup // + +BST_TEMPLATE +typename BST::iterator BST:: + find(const Key& key) +{ + node* n = _root; + + while (n) + { + if (_comp(key, n->value.first)) + n = n->left; + else if (_comp(n->value.first, key)) + n = n->right; + else + return (iterator(n, _sentinel)); + } + return (end()); +} + +BST_TEMPLATE +typename BST::const_iterator BST:: + find(const Key& key) const +{ + node* n = _root; + + while (n) + { + if (_comp(key, n->value.first)) + n = n->left; + else if (_comp(n->value.first, key)) + n = n->right; + else + return (const_iterator(n, _sentinel)); + } + return (end()); +} + +BST_TEMPLATE +typename BST::size_type BST:: + count(const Key& key) const +{ + if (find(key) != end()) + return (1); + else + return (0); +} + + + /////////////////////// + // Private functions // + +BST_TEMPLATE +void BST:: + _init_sentinel() +{ + _sentinel = _allocator_node_sentinel.allocate(1); + _allocator_node_sentinel.construct(_sentinel, node_sentinel()); +} + +BST_TEMPLATE +pair BST:: + _insert(const value_type& value) +{ + node* n = _root; + node* prev = NULL; + + while (n) + { + prev = n; + if (_comp(value.first, n->value.first)) + n = n->left; + else if (_comp(n->value.first, value.first)) + n = n->right; + else + return ft::make_pair(iterator(n, _sentinel), false); + } + + n = _allocator_node.allocate(1); + _allocator_node.construct(n, node(value)); + if (_root == NULL) // if (_size == 0) + { + _root = n; + _sentinel->child = _root; + } + else if (_comp(value.first, prev->value.first)) + prev->left = n; + else + prev->right = n; + n->up = prev; + ++_size; + return ft::make_pair(iterator(n, _sentinel), true); +} + +BST_TEMPLATE +node* BST:: + _erase(iterator pos) +{ + node* n = pos.getNode(); + node* delete_point = NULL; + + if (n->left && n->right) // 2 child + { + node* next = n->right->min(); + + if (next->up != n) + { + _subtree_shift(next, next->right); + next->right = n->right; + next->right->up = next; + } + delete_point = _subtree_shift(n, next); + next->left = n->left; + next->left->up = next; + } + else if (!n->left && !n->right) // no child (leaf) + delete_point = _subtree_shift(n, NULL); // bug ? + else if (n->left) // 1 child + delete_point = _subtree_shift(n, n->left); + else if (n->right) // 1 child + delete_point = _subtree_shift(n, n->right); // bug ? + + _allocator_node.destroy(n); + _allocator_node.deallocate(n, 1); + --_size; + return (delete_point); +} + +BST_TEMPLATE +node* BST:: + _subtree_shift(node* st_old, node* st_new) +{ + node* p = st_old->up; + + if (st_old == _root) + { + _root = st_new; + _sentinel->child = _root; + } + else if (st_old == p->left) + p->left = st_new; + else + p->right = st_new; + + if (st_new == NULL) + return (p); // return deletion point + st_new->up = p; + return (st_new); // return deletion point +} + +BST_TEMPLATE +void BST:: + _insert_rebalancing(node* n) +{ + node* old_n; + node* parent = NULL; + + while (n) + { + n->height = _compute_height(n); + + if (_bf(n) > 1) // Left Heavy + { + parent = n->up; + if (_bf(n->left) < 0) // Left-Right Case (BF == -1) + n->left = _rotate_left(n->left); + // Left-Left Case + n = _rotate_right(n); + old_n = n->right; + } + else if (_bf(n) < -1) // Right Heavy + { + parent = n->up; + if (_bf(n->right) > 0) // Right-Left Case (BF == 1) + n->right = _rotate_right(n->right); + // Right-Right Case + n = _rotate_left(n); + old_n = n->left; + } + + if (parent) + { + if (parent->left == old_n) + parent->left = n; + else + parent->right = n; + break; + } + + n = n->up; + } + + while (n) + { + n->height = _compute_height(n); + n = n->up; + } +} + +BST_TEMPLATE +void BST:: + _erase_rebalancing(node* n) +{ + node* old_n; + node* parent = NULL; + + while (n) + { + n->height = _compute_height(n); + + if (_bf(n) > 1) // Left Heavy + { + parent = n->up; + if (_bf(n->left) < 0) // Left-Right Case (BF == -1) + n->left = _rotate_left(n->left); + // Left-Left Case + n = _rotate_right(n); + old_n = n->right; + } + else if (_bf(n) < -1) // Right Heavy + { + parent = n->up; + if (_bf(n->right) > 0) // Right-Left Case (BF == 1) + n->right = _rotate_right(n->right); + // Right-Right Case + n = _rotate_left(n); + old_n = n->left; + } + + if (parent) + { + if (parent->left == old_n) + parent->left = n; + else + parent->right = n; + parent = NULL; + } + + n = n->up; + } +} + +BST_TEMPLATE +short BST:: + _compute_height(node* n) +{ + if (n->left && n->right) + return std::max(n->left->height, n->right->height) + 1; + else if (n->left) + return n->left->height + 1; + else if (n->right) + return n->right->height + 1; + else + return 1; +} + +BST_TEMPLATE +short BST:: + _bf(node* n) // optimisation possible if assume n have at least one child ? +{ + if (n->left && n->right) + return n->left->height - n->right->height; + else if (n->left) + return n->left->height; + else if (n->right) + return (-(n->right->height)); + else + return 0; +} + +BST_TEMPLATE +node* BST:: + _rotate_left(node* n) // assume n->right != NULL +{ + node* ori_right = n->right; + + ori_right->up = n->up; + n->up = ori_right; + + n->right = ori_right->left; + if (n->right != NULL) + n->right->up = n; + ori_right->left = n; + + n->height = _compute_height(n); + ori_right->height = _compute_height(ori_right); + + if (n == _root) + { + _root = ori_right; + _sentinel->child = _root; + } + + return ori_right; // return new sub-tree root +} + +BST_TEMPLATE +node* BST:: + _rotate_right(node* n) // assume n->left != NULL +{ + node* ori_left = n->left; + + ori_left->up = n->up; + n->up = ori_left; + + n->left = ori_left->right; + if (n->left != NULL) + n->left->up = n; + ori_left->right = n; + + n->height = _compute_height(n); + ori_left->height = _compute_height(ori_left); + + if (n == _root) + { + _root = ori_left; + _sentinel->child = _root; + } + + return ori_left; // return new sub-tree root +} + + + ////////////////////////// + // Non-member functions // + +BST_TEMPLATE +bool operator==(const BST& lhs, const BST& rhs) +{ + if (lhs.size() != rhs.size()) + return false; + return ft::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +BST_TEMPLATE +bool operator!=(const BST& lhs, const BST& rhs) + { return !(lhs == rhs); } + + +BST_TEMPLATE +bool operator<(const BST& lhs, const BST& rhs) +{ + return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +BST_TEMPLATE +bool operator>(const BST& lhs, const BST& rhs) + { return (rhs < lhs); } + +BST_TEMPLATE +bool operator<=(const BST& lhs, const BST& rhs) + { return !(lhs > rhs); } + +BST_TEMPLATE +bool operator>=(const BST& lhs, const BST& rhs) + { return !(lhs < rhs); } + + +BST_TEMPLATE +void swap(BST& lhs, BST& rhs) + { lhs.swap(rhs); } + + +} // namespace ft + +#undef BST +#undef BST_TEMPLATE + diff --git a/templates/map.tpp b/templates/map.tpp index c584390..e0df93d 100644 --- a/templates/map.tpp +++ b/templates/map.tpp @@ -61,7 +61,11 @@ MP_TPL MP:: * element access : ******************/ //// operator[] -------------------------------- -// mapped_type & operator[] (const key_type& k); +MP_TPL typename MP::mapped_type& MP:: + operator[] (const key_type& k) { + + return _bst[k]; +} /************* diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index d257f0f..b5129f1 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -10,10 +10,11 @@ TEST_M(tests_map_simple) TITLE(simple test) typename ft::map mp; -// typename std::map::iterator it; -// -// mp[VALT('a')] = VALU(10); -// + typename std::map::iterator it; + + mp[VALT('a')] = VALU(10); + +// it = mp.begin(); // PRINT(mp) DELETE From 28acc5ef51c3fd83dc7159df26b724237dfcd81b Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 21 Jun 2022 01:50:41 +0200 Subject: [PATCH 38/53] map filled luky style --- headers/map.hpp | 199 +++++++++++++++--------------- templates/map.tpp | 288 ++++++++++++++++++++++++++++++-------------- tests/tests_map.cpp | 3 +- 3 files changed, 301 insertions(+), 189 deletions(-) diff --git a/headers/map.hpp b/headers/map.hpp index c00ade3..e4c51fa 100644 --- a/headers/map.hpp +++ b/headers/map.hpp @@ -36,137 +36,138 @@ public: typedef Bst bst_map; -// typedef typename bst_map::iterator iterator; -// typedef typename bst_map::const_iterator const_iterator; -// typedef typename bst_map::reverse_iterator reverse_iterator; -// typedef typename bst_map::const_reverse_iterator const_reverse_iterator; + typedef typename bst_map::iterator iterator; + typedef typename bst_map::const_iterator const_iterator; + typedef typename bst_map::reverse_iterator reverse_iterator; + typedef typename bst_map::const_reverse_iterator const_reverse_iterator; /**************** * member class : ****************/ -// // https://en.cppreference.com/w/cpp/container/map/value_compare -// class value_compare : public std::binary_function -// { -// friend class map; -// protected: -// Compare comp; -// value_compare(Compare c) : comp(c) {} -// public: -// bool operator() (const value_type& x, const value_type& y) const -// { return comp(x.first, y.first); } -// }; + // https://en.cppreference.com/w/cpp/container/map/value_compare + // https://stackoverflow.com/questions/4571355/why-would-one-use-nested-classes-in-c + class value_compare : public std::binary_function { + + friend class map; + protected: + Compare comp; + value_compare(Compare c) : comp(c) {} + public: + bool operator() (const value_type& x, const value_type& y) const + { return comp(x.first, y.first); } + }; /************ * copliens : ************/ -//// constructors ------------------------------ +// constructors ------------------------------ explicit map (const key_compare& comp = key_compare(), const allocator_type& alloc = allocator_type()); -// template -// map (InputIterator first, InputIterator last, -// const key_compare& comp = key_compare(), -// const allocator_type& alloc = allocator_type()); -// map (const map& x); -//// destructor -------------------------------- -// ~map(); -//// operator= --------------------------------- -// map& operator= (const map& x); + template + map (InputIterator first, InputIterator last, + const key_compare& comp = key_compare(), + const allocator_type& alloc = allocator_type()); + map (const map& x); +// destructor -------------------------------- + ~map(); +// operator= --------------------------------- + map& operator= (const map& x); /************* * iterators : *************/ -//// begin ------------------------------------- -// iterator begin(); -// const_iterator begin() const; -//// end --------------------------------------- -// iterator end(); -// const_iterator end() const; -//// rbegin ------------------------------------ -// reverse_iterator rbegin(); -// const_reverse_iterator rbegin() const; -//// rend -------------------------------------- -// reverse_iterator rend(); -// const_reverse_iterator rend() const; +// begin ------------------------------------- + iterator begin(); + const_iterator begin() const; +// end --------------------------------------- + iterator end(); + const_iterator end() const; +// rbegin ------------------------------------ + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; +// rend -------------------------------------- + reverse_iterator rend(); + const_reverse_iterator rend() const; /************ * capacity : ************/ -//// empty ------------------------------------- -// bool empty() const; -//// size -------------------------------------- -// size_type size() const; -//// max_size ---------------------------------- -// size_type max_size() const; +// empty ------------------------------------- + bool empty() const; +// size -------------------------------------- + size_type size() const; +// max_size ---------------------------------- + size_type max_size() const; /****************** * element access : ******************/ -//// operator[] -------------------------------- +// operator[] -------------------------------- mapped_type & operator[] (const key_type& k); /************* * modifiers : *************/ -//// insert ------------------------------------ -// pair insert (const value_type& val); -// iterator insert (iterator position, const value_type& val); -// template -// void insert (InputIterator first, InputIterator last); -//// erase ------------------------------------- -// void erase (iterator position); -// size_type erase (const key_type& k); -// void erase (iterator first, iterator last); -//// swap -------------------------------------- -// void swap (map& x); -//// clear ------------------------------------- -// void clear(); +// insert ------------------------------------ + pair insert (const value_type& val); + iterator insert (iterator position, const value_type& val); + template + void insert (InputIterator first, InputIterator last); +// erase ------------------------------------- + void erase (iterator position); + size_type erase (const key_type& k); + void erase (iterator first, iterator last); +// swap -------------------------------------- + void swap (map& x); +// clear ------------------------------------- + void clear(); /************* * observers : *************/ -//// key_comp ---------------------------------- -// key_compare key_comp() const; -//// value_comp -------------------------------- -// value_compare value_comp() const; +// key_comp ---------------------------------- + key_compare key_comp() const; +// value_comp -------------------------------- + value_compare value_comp() const; /************** * operations : **************/ -//// find -------------------------------------- -// iterator find (const key_type& k); -// const_iterator find (const key_type& k) const; -//// count ------------------------------------- -// size_type count (const key_type& k) const; -//// lower_bound ------------------------------- -// iterator lower_bound (const key_type& k); -// const_iterator lower_bound (const key_type& k) const; -//// upper_bound ------------------------------- -// iterator upper_bound (const key_type& k); -// const_iterator upper_bound (const key_type& k) const; -//// equal_range ------------------------------- -// pair equal_range (const key_type& k) const; -// pair equal_range (const key_type& k); +// find -------------------------------------- + iterator find (const key_type& k); + const_iterator find (const key_type& k) const; +// count ------------------------------------- + size_type count (const key_type& k) const; +// lower_bound ------------------------------- + iterator lower_bound (const key_type& k); + const_iterator lower_bound (const key_type& k) const; +// upper_bound ------------------------------- + iterator upper_bound (const key_type& k); + const_iterator upper_bound (const key_type& k) const; +// equal_range ------------------------------- + pair equal_range (const key_type& k) const; + pair equal_range (const key_type& k); /************* * allocator : *************/ -//// get_allocator ----------------------------- -// allocator_type get_allocator() const; +// get_allocator ----------------------------- + allocator_type get_allocator() const; private: + bst_map _bst; allocator_type _allocator; key_compare _comp; - bst_map _bst; }; @@ -174,27 +175,27 @@ private: /************************ * non-member functions : ************************/ -//// operator == ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator== -// ( const std::map& lhs, const std::map& rhs ); -//// operator != ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator!= -// ( const std::map& lhs, const std::map& rhs ); -//// operator < -------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator< -// ( const std::map& lhs, const std::map& rhs ); -//// operator <= ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator<= -// ( const std::map& lhs, const std::map& rhs ); -//// operator > -------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator> -// ( const std::map& lhs, const std::map& rhs ); -//// operator >= ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator>= -// ( const std::map& lhs, const std::map& rhs ); -//// swap (map) ----------------------------- -//template< class Key, class T, class Compare, class Alloc > void swap -// ( std::map& lhs, std::map& rhs ); +// operator == ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator== + ( const std::map& lhs, const std::map& rhs ); +// operator != ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator!= + ( const std::map& lhs, const std::map& rhs ); +// operator < -------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator< + ( const std::map& lhs, const std::map& rhs ); +// operator <= ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator<= + ( const std::map& lhs, const std::map& rhs ); +// operator > -------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator> + ( const std::map& lhs, const std::map& rhs ); +// operator >= ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator>= + ( const std::map& lhs, const std::map& rhs ); +// swap (map) ----------------------------- +template< class Key, class T, class Compare, class Alloc > void swap + ( std::map& lhs, std::map& rhs ); } // namespace ft diff --git a/templates/map.tpp b/templates/map.tpp index e0df93d..506a818 100644 --- a/templates/map.tpp +++ b/templates/map.tpp @@ -10,141 +10,253 @@ namespace ft { /************ * copliens : ************/ -//// constructors ------------------------------ +// constructors ------------------------------ MP_TPL MP:: map (const key_compare & comp, const allocator_type & alloc) - : _allocator(alloc) + : _bst() + , _allocator(alloc) , _comp(comp) { return; } -// template -// map (InputIterator first, InputIterator last, -// const key_compare& comp = key_compare(), -// const allocator_type& alloc = allocator_type()); -// map (const map& x); -//// destructor -------------------------------- -// ~map(); -//// operator= --------------------------------- -// map& operator= (const map& x); +MP_TPL template MP:: + map (InputIt first, InputIt last, const key_compare& comp, const allocator_type& alloc) + : _bst(first, last) + , _allocator(alloc) + , _comp(comp) { +} +MP_TPL MP:: + map (const map& x) + : _bst() + , _allocator(x._allocator) + , _comp(x._comp) { + + *this = x; +} +// destructor -------------------------------- +MP_TPL MP:: + ~map() { clear(); } +// operator= --------------------------------- +MP_TPL MP& MP:: + operator= (const map& x) { + + if (this == &x) + return (*this); + + map new_map(x.begin(), x.end()); + swap(new_map); + return (*this); +} /************* * iterators : *************/ -//// begin ------------------------------------- -// iterator begin(); -// const_iterator begin() const; -//// end --------------------------------------- -// iterator end(); -// const_iterator end() const; -//// rbegin ------------------------------------ -// reverse_iterator rbegin(); -// const_reverse_iterator rbegin() const; -//// rend -------------------------------------- -// reverse_iterator rend(); -// const_reverse_iterator rend() const; +// begin ------------------------------------- +MP_TPL typename MP::iterator MP:: + begin() { return (_bst.begin()); } +MP_TPL typename MP::const_iterator MP:: + begin() const { return (_bst.begin()); } +// end --------------------------------------- +MP_TPL typename MP::iterator MP:: + end() { return (_bst.end()); } +MP_TPL typename MP::const_iterator MP:: + end() const { return (_bst.end()); } +// rbegin ------------------------------------ +MP_TPL typename MP::reverse_iterator MP:: + rbegin() { return (_bst.rbegin()); } +MP_TPL typename MP::const_reverse_iterator MP:: + rbegin() const { return (_bst.rbegin()); } +// rend -------------------------------------- +MP_TPL typename MP::reverse_iterator MP:: + rend() { return (_bst.rend()); } +MP_TPL typename MP::const_reverse_iterator MP:: + rend() const { return (_bst.rend()); } /************ * capacity : ************/ -//// empty ------------------------------------- -// bool empty() const; -//// size -------------------------------------- -// size_type size() const; -//// max_size ---------------------------------- -// size_type max_size() const; +// empty ------------------------------------- +MP_TPL bool MP:: + empty() const { return (_bst.empty()); } +// size -------------------------------------- +MP_TPL typename MP::size_type MP:: + size() const { return (_bst.size()); } +// max_size ---------------------------------- +MP_TPL typename MP::size_type MP:: + max_size() const { return (_bst.max_size()); } /****************** * element access : ******************/ -//// operator[] -------------------------------- +// operator[] -------------------------------- MP_TPL typename MP::mapped_type& MP:: - operator[] (const key_type& k) { - - return _bst[k]; -} + operator[] (const key_type& k) { return _bst[k]; } /************* * modifiers : *************/ -//// insert ------------------------------------ -// pair insert (const value_type& val); -// iterator insert (iterator position, const value_type& val); -// template -// void insert (InputIterator first, InputIterator last); -//// erase ------------------------------------- -// void erase (iterator position); -// size_type erase (const key_type& k); -// void erase (iterator first, iterator last); -//// swap -------------------------------------- -// void swap (map& x); -//// clear ------------------------------------- -// void clear(); +// insert ------------------------------------ +MP_TPL pair MP:: + insert (const value_type& val) { return (_bst.insert(val)); } +MP_TPL typename MP::iterator MP:: + insert (iterator pos, const value_type& val) { return (_bst.insert(pos, val)); } +MP_TPL template void MP:: + insert (InputIt first, InputIt last) { return (_bst.insert(first, last)); } +// erase ------------------------------------- +MP_TPL void MP:: + erase (iterator pos) { return (_bst.erase(pos)); } +MP_TPL typename MP::size_type MP:: + erase (const key_type& k) { return (_bst.erase(k)); } +MP_TPL void MP:: + erase (iterator first, iterator last) { return (_bst.erase(first, last)); } +// swap -------------------------------------- +MP_TPL void MP:: + swap (map& x) { + + bst_map tmp; + + tmp.swap(_bst); + _bst.swap(x._bst); + x._bst.swap(tmp); +} + +// clear ------------------------------------- +MP_TPL void MP:: + clear() { + + _bst.clear(); +} /************* * observers : *************/ -//// key_comp ---------------------------------- -// key_compare key_comp() const; -//// value_comp -------------------------------- -// value_compare value_comp() const; +// key_comp ---------------------------------- +MP_TPL typename MP::key_compare MP:: + key_comp() const { return (value_compare(_comp).comp); } +// value_comp -------------------------------- +MP_TPL typename MP::value_compare MP:: + value_comp() const { return (value_compare(_comp)); } /************** * operations : **************/ -//// find -------------------------------------- -// iterator find (const key_type& k); -// const_iterator find (const key_type& k) const; -//// count ------------------------------------- -// size_type count (const key_type& k) const; -//// lower_bound ------------------------------- -// iterator lower_bound (const key_type& k); -// const_iterator lower_bound (const key_type& k) const; -//// upper_bound ------------------------------- -// iterator upper_bound (const key_type& k); -// const_iterator upper_bound (const key_type& k) const; -//// equal_range ------------------------------- -// pair equal_range (const key_type& k) const; -// pair equal_range (const key_type& k); +// find -------------------------------------- +MP_TPL typename MP::iterator MP:: + find (const key_type& k) { return (_bst.find(k)); } +MP_TPL typename MP::const_iterator MP:: + find (const key_type& k) const { return (_bst.find(k)); } +// count ------------------------------------- +MP_TPL typename MP::size_type MP:: + count (const key_type& k) const { return (_bst.count(k)); } +// lower_bound ------------------------------- +MP_TPL typename MP::iterator MP:: + lower_bound (const key_type& k) { + + iterator it = begin(); + iterator it_end = end(); + + while (it != it_end) + { + if (_comp(it->first, k) == false) + return (it); + ++it; + } + return (it_end); +} +MP_TPL typename MP::const_iterator MP:: + lower_bound (const key_type& k) const { + + const_iterator it = begin(); + const_iterator it_end = end(); + + while (it != it_end) + { + if (_comp(it->first, k) == false) + return (it); + ++it; + } + return (it_end); +} +// upper_bound ------------------------------- +MP_TPL typename MP::iterator MP:: + upper_bound (const key_type& k) { + + iterator it = begin(); + iterator it_end = end(); + + while (it != it_end) + { + if (_comp(k, it->first)) + return (it); + ++it; + } + return (it_end); +} +MP_TPL typename MP::const_iterator MP:: + upper_bound (const key_type& k) const { + + const_iterator it = begin(); + const_iterator it_end = end(); + + while (it != it_end) + { + if (_comp(k, it->first)) + return (it); + ++it; + } + return (it_end); +} +// equal_range ------------------------------- +MP_TPL pair MP:: + equal_range (const key_type& k) const { + + return ft::make_pair( lower_bound(k), upper_bound(k) ); +} +MP_TPL pair MP:: + equal_range (const key_type& k) { + + return ft::make_pair( lower_bound(k), upper_bound(k) ); +} /************* * allocator : *************/ -//// get_allocator ----------------------------- -// allocator_type get_allocator() const; +// get_allocator ----------------------------- +MP_TPL typename MP::allocator_type MP:: + get_allocator() const { return (_allocator); } /************************ * non-member functions : ************************/ -//// operator == ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator== -// ( const std::map& lhs, const std::map& rhs ); -//// operator != ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator!= -// ( const std::map& lhs, const std::map& rhs ); -//// operator < -------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator< -// ( const std::map& lhs, const std::map& rhs ); -//// operator <= ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator<= -// ( const std::map& lhs, const std::map& rhs ); -//// operator > -------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator> -// ( const std::map& lhs, const std::map& rhs ); -//// operator >= ------------------------------- -//template< class K, class T, class Comp, class Alloc > bool operator>= -// ( const std::map& lhs, const std::map& rhs ); -//// swap (map) ----------------------------- -//template< class Key, class T, class Compare, class Alloc > void swap -// ( std::map& lhs, std::map& rhs ); +// operator == ------------------------------- +template< class Key, class T, class Compare, class Alloc > bool operator== + ( const MP& lhs, const MP& rhs ) { return (lhs._bst == rhs._bst); } +// operator != ------------------------------- +template< class Key, class T, class Compare, class Alloc > bool operator!= + ( const MP& lhs, const MP& rhs ) { return (lhs._bst != rhs._bst); } +// operator < -------------------------------- +template< class Key, class T, class Compare, class Alloc > bool operator< + ( const MP& lhs, const MP& rhs ) { return (lhs._bst < rhs._bst); } +// operator <= ------------------------------- +template< class Key, class T, class Compare, class Alloc > bool operator<= + ( const MP& lhs, const MP& rhs ) { return (lhs._bst <= rhs._bst); } +// operator > -------------------------------- +template< class Key, class T, class Compare, class Alloc > bool operator> + ( const MP& lhs, const MP& rhs ) { return (lhs._bst > rhs._bst); } +// operator >= ------------------------------- +template< class Key, class T, class Compare, class Alloc > bool operator>= + ( const MP& lhs, const MP& rhs ) { return (lhs._bst >= rhs._bst); } +// swap (map) ----------------------------- +template< class Key, class T, class Compare, class Alloc > void swap + ( const MP& lhs, const MP& rhs ) { lhs.swap(rhs); } } // namespace ft diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index b5129f1..ecb4a1d 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -14,8 +14,7 @@ TEST_M(tests_map_simple) mp[VALT('a')] = VALU(10); -// it = mp.begin(); -// PRINT(mp) + PRINT(mp) DELETE } From 844701201f1de748130623f1552022da63ca9784 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 21 Jun 2022 14:41:24 +0200 Subject: [PATCH 39/53] half tests ok on map --- tests/includes/main.hpp | 44 +++++----- tests/includes/tests_utils.hpp | 35 ++++++-- tests/main.cpp | 20 ++--- tests/tests_map.cpp | 145 +++++++++++++++++---------------- tests/tests_vector.cpp | 21 ----- 5 files changed, 135 insertions(+), 130 deletions(-) diff --git a/tests/includes/main.hpp b/tests/includes/main.hpp index 42a0876..fafcf6a 100644 --- a/tests/includes/main.hpp +++ b/tests/includes/main.hpp @@ -47,28 +47,28 @@ void tests_vector_swap_non_member(); void tests_vector_reverse_iterators(); // map void tests_map_simple(); -//void tests_map_constructor(); -//void tests_map_operator_assignation(); -//void tests_map_begin(); -//void tests_map_end(); -//void tests_map_rbegin(); -//void tests_map_rend(); -//void tests_map_empty(); -//void tests_map_size(); -//void tests_map_max_size(); -//void tests_map_operator_access(); -//void tests_map_insert(); -//void tests_map_erase(); -//void tests_map_swap(); -//void tests_map_clear(); -//void tests_map_key_comp(); -//void tests_map_value_comp(); -//void tests_map_find(); -//void tests_map_count(); -//void tests_map_lower_bound(); -//void tests_map_upper_bound(); -//void tests_map_equal_range(); -//void tests_map_get_allocator(); +void tests_map_constructor(); +void tests_map_operator_assignation(); +void tests_map_begin(); +void tests_map_end(); +void tests_map_rbegin(); +void tests_map_rend(); +void tests_map_empty(); +void tests_map_size(); +void tests_map_max_size(); +void tests_map_operator_access(); +void tests_map_insert(); +void tests_map_erase(); +void tests_map_swap(); +void tests_map_clear(); +void tests_map_key_comp(); +void tests_map_value_comp(); +void tests_map_find(); +void tests_map_count(); +void tests_map_lower_bound(); +void tests_map_upper_bound(); +void tests_map_equal_range(); +void tests_map_get_allocator(); #endif diff --git a/tests/includes/tests_utils.hpp b/tests/includes/tests_utils.hpp index 170c866..ee20cfa 100644 --- a/tests/includes/tests_utils.hpp +++ b/tests/includes/tests_utils.hpp @@ -32,7 +32,7 @@ # define VALT(n) val(n) # define VALU(n) val(n) # define TOI(n) toi(n) -# define PRINT(n) print(n); +# define PRINT(n) print<>(n, #n); # define DELETE delete_structs(); @@ -82,7 +82,10 @@ extern std::vector< mystruct* > mem_list; template struct s_ ## f_name : public A_test\ { void func(); };\ void f_name () {\ - add_to_list(#f_name, "int, int", new(s_ ## f_name ));\ + add_to_list(#f_name, "char, int", new(s_ ## f_name ));\ + add_to_list(#f_name, "char, char", new(s_ ## f_name ));\ + add_to_list(#f_name, "char, std::string", new(s_ ## f_name ));\ + add_to_list(#f_name, "char, mystruct*", new(s_ ## f_name ));\ }\ template \ void s_ ## f_name ::func() @@ -91,23 +94,25 @@ extern std::vector< mystruct* > mem_list; // templates print // ***************************************** template - void print(ft::vector vec) { + void print(ft::vector vec, std::string name) { int i = 0; typename ft::vector::iterator it; typename ft::vector::iterator it_end = vec.end(); + std::cout << "\n" << name << ":(vector)\n"; for (it = vec.begin(); it != it_end; ++it, i++) std::cout << "[" << i << "]" << *it << " "; std::cout << "\nsize:" << vec.size() << " capacty:" << vec.capacity() << "\n"; } template - void print(ft::map mp) { + void print(ft::map mp, std::string name) { int i = 0; typename ft::map::iterator it; typename ft::map::iterator it_end = mp.end(); + std::cout << "\n" << name << ":(map)\n"; for (it = mp.begin(); it != it_end; ++it, i++) std::cout << "[" << i << "]" << it->first << ":" << it->second << " "; std::cout << "\nsize:" << mp.size() << "\n"; @@ -118,13 +123,15 @@ template // specialization in header, make it inline : // https://stackoverflow.com/questions/63529059/c-specialized-method-templates-produce-multiple-definition-errors template - T val(int n) {(void)n; return (T()); -} + T val(int n) { (void)n; return (T()); } template <> - inline int val(int n) {return (n); -} + inline int val(int n) { return (n); } template <> - inline char val(int n) {return (n % 94 + 33); + inline char val(int n) { + + if (n <= 126 && n >= 33) + return n; + return (n % 94 + 33); } template <> inline std::string val(int n) { @@ -144,6 +151,16 @@ template <> mem_list.push_back(s); return ( s ); } +template + T val(std::string str) { (void)str; return (T()); } +template <> + inline int val(std::string str) { int i = str[0]; return (val(i)); } +template <> + inline char val(std::string str) { int i = str[0]; return (val(i)); } +template <> + inline std::string val(std::string str) { return (str); } +template <> + inline mystruct* val(std::string str) { int i = str[0]; return (val(i)); } // templates to value diff --git a/tests/main.cpp b/tests/main.cpp index 17a98e1..cbf0a51 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -35,16 +35,16 @@ int main() { // MAP tests_map_simple(); -// tests_map_constructor(); -// tests_map_operator_assignation(); -// tests_map_begin(); -// tests_map_end(); -// tests_map_rbegin(); -// tests_map_rend(); -// tests_map_empty(); -// tests_map_size(); -// tests_map_max_size(); -// tests_map_operator_access(); + tests_map_constructor(); + tests_map_operator_assignation(); + tests_map_begin(); + tests_map_end(); + tests_map_rbegin(); + tests_map_rend(); + tests_map_empty(); + tests_map_size(); + tests_map_max_size(); + tests_map_operator_access(); // tests_map_insert(); // tests_map_erase(); // tests_map_swap(); diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index ecb4a1d..b74ab47 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -4,6 +4,15 @@ #include "tests_utils.hpp" +/**/ // UTILS for some tests +/**/ bool fncomp (char lhs, char rhs) {return lhs first; - std::map first; + first[VALT('a')]=VALU(10); + first[VALT('b')]=VALU(30); + first[VALT('c')]=VALU(50); + first[VALT('d')]=VALU(70); - first['a']=10; - first['b']=30; - first['c']=50; - first['d']=70; + ft::map second (first.begin(),first.end()); - std::map second (first.begin(),first.end()); + ft::map third (second); - std::map third (second); - - std::map fourth; // class as Compare + ft::map fourth; // class as Compare bool(*fn_pt)(char,char) = fncomp; - std::map fifth (fn_pt); // function pointer as Compare + ft::map fifth (fn_pt); // function pointer as Compare + + PRINT(first) + PRINT(second) + PRINT(third) DELETE } @@ -56,19 +61,25 @@ TEST_M(tests_map_operator_assignation) // title TITLE(cplusplus.com reference) - std::map first; - std::map second; + ft::map first; + ft::map second; - first['x']=8; - first['y']=16; - first['z']=32; + first[VALT('x')]=VALU(8); + first[VALT('y')]=VALU(16); + first[VALT('z')]=VALU(32); + + PRINT(first) + PRINT(second) second=first; // second now contains 3 ints - first=std::map(); // and first is now empty + first=ft::map(); // and first is now empty std::cout << "Size of first: " << first.size() << '\n'; std::cout << "Size of second: " << second.size() << '\n'; + PRINT(first) + PRINT(second) + DELETE } @@ -77,15 +88,13 @@ TEST_M(tests_map_begin) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['b'] = 100; - mymap['a'] = 200; - mymap['c'] = 300; + mymap[VALT('b')] = VALU(100); + mymap[VALT('a')] = VALU(200); + mymap[VALT('c')] = VALU(300); - // show content: - for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) DELETE } @@ -95,15 +104,13 @@ TEST_M(tests_map_end) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['b'] = 100; - mymap['a'] = 200; - mymap['c'] = 300; + mymap[VALT('b')] = VALU(100); + mymap[VALT('a')] = VALU(200); + mymap[VALT('c')] = VALU(300); - // show content: - for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) DELETE } @@ -113,14 +120,14 @@ TEST_M(tests_map_rbegin) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['x'] = 100; - mymap['y'] = 200; - mymap['z'] = 300; + mymap[VALT('x')] = VALU(100); + mymap[VALT('y')] = VALU(200); + mymap[VALT('z')] = VALU(300); // show content: - std::map::reverse_iterator rit; + typename ft::map::reverse_iterator rit; for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit) std::cout << rit->first << " => " << rit->second << '\n'; @@ -132,14 +139,14 @@ TEST_M(tests_map_rend) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['x'] = 100; - mymap['y'] = 200; - mymap['z'] = 300; + mymap[VALT('x')] = VALU(100); + mymap[VALT('y')] = VALU(200); + mymap[VALT('z')] = VALU(300); // show content: - std::map::reverse_iterator rit; + typename ft::map::reverse_iterator rit; for (rit=mymap.rbegin(); rit!=mymap.rend(); ++rit) std::cout << rit->first << " => " << rit->second << '\n'; @@ -151,16 +158,16 @@ TEST_M(tests_map_empty) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['a']=10; - mymap['b']=20; - mymap['c']=30; + mymap[VALT('a')]=VALU(10); + mymap[VALT('b')]=VALU(20); + mymap[VALT('c')]=VALU(30); while (!mymap.empty()) { - std::cout << mymap.begin()->first << " => " << mymap.begin()->second << '\n'; - mymap.erase(mymap.begin()); + std::cout << mymap.begin()->first << " => " << mymap.begin()->second << '\n'; + mymap.erase(mymap.begin()); } DELETE @@ -171,13 +178,15 @@ TEST_M(tests_map_size) // title TITLE(cplusplus.com reference) - std::map mymap; - mymap['a']=101; - mymap['b']=202; - mymap['c']=302; + ft::map mymap; + mymap[VALT('a')]=VALU(101); + mymap[VALT('b')]=VALU(202); + mymap[VALT('c')]=VALU(302); std::cout << "mymap.size() is " << mymap.size() << '\n'; + PRINT(mymap) + DELETE } @@ -187,11 +196,11 @@ TEST_M(tests_map_max_size) TITLE(cplusplus.com reference) int i; - std::map mymap; + std::map mymap; if (mymap.max_size()>1000) { - for (i=0; i<1000; i++) mymap[i]=0; + for (i=0; i<1000; i++) mymap[i]=VALU(0); std::cout << "The map contains 1000 elements.\n"; } else std::cout << "The map could not hold 1000 elements.\n"; @@ -204,22 +213,23 @@ TEST_M(tests_map_operator_access) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['a']="an element"; - mymap['b']="another element"; - mymap['c']=mymap['b']; + mymap[VALT('a')]=VALU("An element"); + mymap[VALT('b')]=VALU("another element"); + mymap[VALT('c')]=mymap[VAL('b')]; - std::cout << "mymap['a'] is " << mymap['a'] << '\n'; - std::cout << "mymap['b'] is " << mymap['b'] << '\n'; - std::cout << "mymap['c'] is " << mymap['c'] << '\n'; - std::cout << "mymap['d'] is " << mymap['d'] << '\n'; + std::cout << "mymap['a'] is " << mymap[VALT('a')] << '\n'; + std::cout << "mymap['b'] is " << mymap[VALT('b')] << '\n'; + std::cout << "mymap['c'] is " << mymap[VALT('c')] << '\n'; + std::cout << "mymap['d'] is " << mymap[VALT('d')] << '\n'; std::cout << "mymap now contains " << mymap.size() << " elements.\n"; DELETE } +/* TEST_M(tests_map_insert) { // title @@ -604,7 +614,6 @@ TEST_M(tests_map_swap_non_member) DELETE } - */ #endif diff --git a/tests/tests_vector.cpp b/tests/tests_vector.cpp index 86a73d7..87fd466 100644 --- a/tests/tests_vector.cpp +++ b/tests/tests_vector.cpp @@ -42,10 +42,8 @@ TEST_V(tests_vector_operator_assignation) // title TITLE(more informations) - std::cout << "foo:\n"; PRINT(foo); - std::cout << "bar:\n"; PRINT(bar); DELETE @@ -59,7 +57,6 @@ TEST_V(tests_vector_begin) ft::vector myvector; for (int i=1; i<=5; i++) myvector.push_back(VAL(i)); - std::cout << "myvector contains:\n"; PRINT(myvector); DELETE @@ -73,7 +70,6 @@ TEST_V(tests_vector_end) ft::vector myvector; for (int i=1; i<=5; i++) myvector.push_back(VAL(i)); - std::cout << "myvector contains:\n"; PRINT(myvector); DELETE @@ -92,7 +88,6 @@ TEST_V(tests_vector_rbegin) for (; rit!= myvector.rend(); ++rit) *rit = VAL(++i); - std::cout << "myvector contains:"; PRINT(myvector); DELETE @@ -111,7 +106,6 @@ TEST_V(tests_vector_rend) for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit) *rit = VAL(++i); - std::cout << "myvector contains:"; PRINT(myvector); DELETE @@ -172,7 +166,6 @@ TEST_V(tests_vector_resize) myvector.resize(8,VAL(100)); myvector.resize(12); - std::cout << "myvector contains:"; PRINT(myvector); @@ -334,7 +327,6 @@ TEST_V(tests_vector_operator_access) myvector[i]=temp; } - std::cout << "myvector contains:"; PRINT(myvector) DELETE @@ -351,7 +343,6 @@ TEST_V(tests_vector_at) for (unsigned i=0; i myvector3 (3,VAL(100)); @@ -568,7 +557,6 @@ TEST_V(tests_vector_insert) it = myvector3.end(); std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; myvector3.insert ( it , VAL(200) ); - std::cout << "myvector contains:"; PRINT(myvector3) ft::vector myvector4 (3,VAL(100)); @@ -576,7 +564,6 @@ TEST_V(tests_vector_insert) it = myvector4.begin() + 2; std::cout << "\nsize:" << myvector3.size() << " capacity:" << myvector3.capacity() << "\n"; myvector4.insert ( it , VAL(200) ); - std::cout << "myvector contains:"; PRINT(myvector4) @@ -597,7 +584,6 @@ TEST_V(tests_vector_insert) it = myvector5.end() - 2; myvector5.insert (it,2,VAL(550)); - std::cout << "myvector contains:"; PRINT(myvector5) @@ -631,7 +617,6 @@ TEST_V(tests_vector_erase) // erase the first 3 elements: myvector.erase (myvector.begin(),myvector.begin()+3); - std::cout << "myvector contains:"; PRINT(myvector) // title @@ -666,10 +651,8 @@ TEST_V(tests_vector_swap) foo.swap(bar); - std::cout << "foo contains:"; PRINT(foo) - std::cout << "bar contains:"; PRINT(bar) DELETE @@ -685,14 +668,12 @@ TEST_V(tests_vector_clear) myvector.push_back (VAL(200)); myvector.push_back (VAL(300)); - std::cout << "myvector contains:"; PRINT(myvector) myvector.clear(); myvector.push_back (VAL(1101)); myvector.push_back (VAL(2202)); - std::cout << "myvector contains:"; PRINT(myvector) DELETE @@ -752,10 +733,8 @@ TEST_V(tests_vector_swap_non_member) foo.swap(bar); - std::cout << "foo contains:"; PRINT(foo) - std::cout << "bar contains:"; PRINT(bar) DELETE From 0d98268a742cbb5b7fbff1dcaa1d921250192a9e Mon Sep 17 00:00:00 2001 From: hugogogo Date: Tue, 21 Jun 2022 18:38:28 +0200 Subject: [PATCH 40/53] all tests except one ok on map --- headers/map.hpp | 3 +- templates/map.tpp | 22 ++- tests/includes/main.hpp | 2 + tests/includes/tests_utils.hpp | 24 ++- tests/main.cpp | 26 +-- tests/tests_definitions.cpp | 5 +- tests/tests_map.cpp | 332 ++++++++++++++++----------------- 7 files changed, 215 insertions(+), 199 deletions(-) diff --git a/headers/map.hpp b/headers/map.hpp index e4c51fa..76bea02 100644 --- a/headers/map.hpp +++ b/headers/map.hpp @@ -163,9 +163,10 @@ public: // get_allocator ----------------------------- allocator_type get_allocator() const; + // TMP non privat + bst_map _bst; private: - bst_map _bst; allocator_type _allocator; key_compare _comp; diff --git a/templates/map.tpp b/templates/map.tpp index 506a818..354fa0f 100644 --- a/templates/map.tpp +++ b/templates/map.tpp @@ -238,22 +238,28 @@ MP_TPL typename MP::allocator_type MP:: ************************/ // operator == ------------------------------- template< class Key, class T, class Compare, class Alloc > bool operator== - ( const MP& lhs, const MP& rhs ) { return (lhs._bst == rhs._bst); } -// operator != ------------------------------- -template< class Key, class T, class Compare, class Alloc > bool operator!= - ( const MP& lhs, const MP& rhs ) { return (lhs._bst != rhs._bst); } + ( const MP& lhs, const MP& rhs ) { + + return (lhs._bst == rhs._bst); +} // operator < -------------------------------- template< class Key, class T, class Compare, class Alloc > bool operator< - ( const MP& lhs, const MP& rhs ) { return (lhs._bst < rhs._bst); } + ( const MP& lhs, const MP& rhs ) { + + return (lhs._bst < rhs._bst); +} +// operator != ------------------------------- +template< class Key, class T, class Compare, class Alloc > bool operator!= + ( const MP& lhs, const MP& rhs ) { return !(lhs == rhs); } // operator <= ------------------------------- template< class Key, class T, class Compare, class Alloc > bool operator<= - ( const MP& lhs, const MP& rhs ) { return (lhs._bst <= rhs._bst); } + ( const MP& lhs, const MP& rhs ) { return !(lhs > rhs); } // operator > -------------------------------- template< class Key, class T, class Compare, class Alloc > bool operator> - ( const MP& lhs, const MP& rhs ) { return (lhs._bst > rhs._bst); } + ( const MP& lhs, const MP& rhs ) { return (rhs < lhs); } // operator >= ------------------------------- template< class Key, class T, class Compare, class Alloc > bool operator>= - ( const MP& lhs, const MP& rhs ) { return (lhs._bst >= rhs._bst); } + ( const MP& lhs, const MP& rhs ) { return !(lhs < rhs); } // swap (map) ----------------------------- template< class Key, class T, class Compare, class Alloc > void swap ( const MP& lhs, const MP& rhs ) { lhs.swap(rhs); } diff --git a/tests/includes/main.hpp b/tests/includes/main.hpp index fafcf6a..d9d8da6 100644 --- a/tests/includes/main.hpp +++ b/tests/includes/main.hpp @@ -69,6 +69,8 @@ void tests_map_lower_bound(); void tests_map_upper_bound(); void tests_map_equal_range(); void tests_map_get_allocator(); +void tests_map_relational_operators(); +void tests_map_swap_non_member(); #endif diff --git a/tests/includes/tests_utils.hpp b/tests/includes/tests_utils.hpp index ee20cfa..bed6a71 100644 --- a/tests/includes/tests_utils.hpp +++ b/tests/includes/tests_utils.hpp @@ -70,10 +70,11 @@ extern std::vector< mystruct* > mem_list; template struct s_ ## f_name : public A_test\ { void func(); };\ void f_name () {\ + add_to_list("", "", NULL);\ add_to_list(#f_name, "int", new(s_ ## f_name ));\ - add_to_list("", "char", new(s_ ## f_name ));\ - add_to_list("", "std::string", new(s_ ## f_name ));\ - add_to_list("", "mystruct*", new(s_ ## f_name ));\ + add_to_list(#f_name, "char", new(s_ ## f_name ));\ + add_to_list(#f_name, "std::string", new(s_ ## f_name ));\ + add_to_list(#f_name, "mystruct*", new(s_ ## f_name ));\ }\ template \ void s_ ## f_name ::func() @@ -82,14 +83,23 @@ extern std::vector< mystruct* > mem_list; template struct s_ ## f_name : public A_test\ { void func(); };\ void f_name () {\ + add_to_list("", "", NULL);\ + add_to_list(#f_name, "char, mystruct*", new(s_ ## f_name ));\ + add_to_list(#f_name, "int, mystruct*", new(s_ ## f_name ));\ + }\ + template \ + void s_ ## f_name ::func() + +/* add_to_list(#f_name, "char, int", new(s_ ## f_name ));\ add_to_list(#f_name, "char, char", new(s_ ## f_name ));\ add_to_list(#f_name, "char, std::string", new(s_ ## f_name ));\ add_to_list(#f_name, "char, mystruct*", new(s_ ## f_name ));\ - }\ - template \ - void s_ ## f_name ::func() - + add_to_list(#f_name, "int, int", new(s_ ## f_name ));\ + add_to_list(#f_name, "int, char", new(s_ ## f_name ));\ + add_to_list(#f_name, "int, std::string", new(s_ ## f_name ));\ + add_to_list(#f_name, "int, mystruct*", new(s_ ## f_name ));\ +*/ // templates print // ***************************************** diff --git a/tests/main.cpp b/tests/main.cpp index cbf0a51..05fe950 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -45,20 +45,20 @@ int main() { tests_map_size(); tests_map_max_size(); tests_map_operator_access(); -// tests_map_insert(); -// tests_map_erase(); -// tests_map_swap(); -// tests_map_clear(); -// tests_map_key_comp(); -// tests_map_value_comp(); -// tests_map_find(); -// tests_map_count(); -// tests_map_lower_bound(); -// tests_map_upper_bound(); -// tests_map_equal_range(); -// tests_map_get_allocator(); + tests_map_insert(); + tests_map_erase(); + tests_map_swap(); + tests_map_clear(); + tests_map_key_comp(); + tests_map_value_comp(); + tests_map_find(); + tests_map_count(); + tests_map_lower_bound(); + tests_map_upper_bound(); + tests_map_equal_range(); + tests_map_get_allocator(); // tests_map_relational_operators(); -// tests_map_swap_non_member(); + tests_map_swap_non_member(); // STACK diff --git a/tests/tests_definitions.cpp b/tests/tests_definitions.cpp index 511015c..ed3fbd4 100644 --- a/tests/tests_definitions.cpp +++ b/tests/tests_definitions.cpp @@ -10,8 +10,11 @@ void add_to_list(std::string title, std::string type, A_test* test) { std::vector< std::vector >::iterator it; // title != NULL for the first element - if (!title.empty()) + if (test == NULL) + { test_list.push_back(test_sub_list); + return; + } test->title = title; test->type = type; diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index b74ab47..1472110 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -229,42 +229,36 @@ TEST_M(tests_map_operator_access) DELETE } -/* TEST_M(tests_map_insert) { // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; // first insert function version (single parameter): - mymap.insert ( std::pair('a',100) ); - mymap.insert ( std::pair('z',200) ); + mymap.insert ( ft::pair(VALT('a'),VALU(100)) ); + mymap.insert ( ft::pair(VALT('z'),VALU(200)) ); - std::pair::iterator,bool> ret; - ret = mymap.insert ( std::pair('z',500) ); + ft::pair::iterator, bool> ret; + ret = mymap.insert ( ft::pair(VALT('z'),VALU(500)) ); if (ret.second==false) { std::cout << "element 'z' already existed"; std::cout << " with a value of " << ret.first->second << '\n'; } + // second insert function version (with hint position): - std::map::iterator it = mymap.begin(); - mymap.insert (it, std::pair('b',300)); // max efficiency inserting - mymap.insert (it, std::pair('c',400)); // no max efficiency inserting + typename ft::map::iterator it = mymap.begin(); + mymap.insert (it, ft::pair(VALT('b'),VALU(300))); // max efficiency inserting + mymap.insert (it, ft::pair(VALT('c'),VALU(400))); // no max efficiency inserting // third insert function version (range insertion): - std::map anothermap; + ft::map anothermap; anothermap.insert(mymap.begin(),mymap.find('c')); - // showing contents: - std::cout << "mymap contains:\n"; - for (it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; - - std::cout << "anothermap contains:\n"; - for (it=anothermap.begin(); it!=anothermap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) + PRINT(anothermap) DELETE } @@ -274,28 +268,26 @@ TEST_M(tests_map_erase) // title TITLE(cplusplus.com reference) - std::map mymap; - std::map::iterator it; + ft::map mymap; + typename ft::map::iterator it; // insert some values: - mymap['a']=10; - mymap['b']=20; - mymap['c']=30; - mymap['d']=40; - mymap['e']=50; - mymap['f']=60; + mymap[VALT('a')]=VALU(10); + mymap[VALT('b')]=VALU(20); + mymap[VALT('c')]=VALU(30); + mymap[VALT('d')]=VALU(40); + mymap[VALT('e')]=VALU(50); + mymap[VALT('f')]=VALU(60); - it=mymap.find('b'); - mymap.erase (it); // erasing by iterator + it=mymap.find(VALT('b')); + mymap.erase (it); // erasing by iterator - mymap.erase ('c'); // erasing by key + mymap.erase (VALT('c')); // erasing by key - it=mymap.find ('e'); - mymap.erase ( it, mymap.end() ); // erasing by range + it=mymap.find (VALT('e')); + mymap.erase ( it, mymap.end() ); // erasing by range - // show content: - for (it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) DELETE } @@ -305,24 +297,19 @@ TEST_M(tests_map_swap) // title TITLE(cplusplus.com reference) - std::map foo,bar; + ft::map foo,bar; - foo['x']=100; - foo['y']=200; + foo[VALT('x')]=VALU(100); + foo[VALT('y')]=VALU(200); - bar['a']=11; - bar['b']=22; - bar['c']=33; + bar[VALT('a')]=VALU(11); + bar[VALT('b')]=VALU(22); + bar[VALT('c')]=VALU(33); foo.swap(bar); - std::cout << "foo contains:\n"; - for (std::map::iterator it=foo.begin(); it!=foo.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; - - std::cout << "bar contains:\n"; - for (std::map::iterator it=bar.begin(); it!=bar.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(foo) + PRINT(bar) DELETE } @@ -332,23 +319,19 @@ TEST_M(tests_map_clear) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['x']=100; - mymap['y']=200; - mymap['z']=300; + mymap[VALT('x')]=VALU(100); + mymap[VALT('y')]=VALU(200); + mymap[VALT('z')]=VALU(300); - std::cout << "mymap contains:\n"; - for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) mymap.clear(); - mymap['a']=1101; - mymap['b']=2202; + mymap[VALT('a')]=VALU(1101); + mymap[VALT('b')]=VALU(2202); - std::cout << "mymap contains:\n"; - for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) DELETE } @@ -358,19 +341,19 @@ TEST_M(tests_map_key_comp) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - std::map::key_compare mycomp = mymap.key_comp(); + typename ft::map::key_compare mycomp = mymap.key_comp(); - mymap['a']=100; - mymap['b']=200; - mymap['c']=300; + mymap[VALT('a')]=VALU(100); + mymap[VALT('b')]=VALU(200); + mymap[VALT('c')]=VALU(300); std::cout << "mymap contains:\n"; - char highest = mymap.rbegin()->first; // key value of last element + T highest = mymap.rbegin()->first; // key value of last element - std::map::iterator it = mymap.begin(); + typename ft::map::iterator it = mymap.begin(); do { std::cout << it->first << " => " << it->second << '\n'; } while ( mycomp((*it++).first, highest) ); @@ -385,17 +368,17 @@ TEST_M(tests_map_value_comp) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['x']=1001; - mymap['y']=2002; - mymap['z']=3003; + mymap[VALT('x')]=VALU(1001); + mymap[VALT('y')]=VALU(2002); + mymap[VALT('z')]=VALU(3003); std::cout << "mymap contains:\n"; - std::pair highest = *mymap.rbegin(); // last element + ft::pair highest = *mymap.rbegin(); // last element - std::map::iterator it = mymap.begin(); + typename ft::map::iterator it = mymap.begin(); do { std::cout << it->first << " => " << it->second << '\n'; } while ( mymap.value_comp()(*it++, highest) ); @@ -408,23 +391,23 @@ TEST_M(tests_map_find) // title TITLE(cplusplus.com reference) - std::map mymap; - std::map::iterator it; + ft::map mymap; + typename ft::map::iterator it; - mymap['a']=50; - mymap['b']=100; - mymap['c']=150; - mymap['d']=200; + mymap[VALT('a')]=VALU(50); + mymap[VALT('b')]=VALU(100); + mymap[VALT('c')]=VALU(150); + mymap[VALT('d')]=VALU(200); - it = mymap.find('b'); + it = mymap.find(VALT('b')); if (it != mymap.end()) mymap.erase (it); // print content: std::cout << "elements in mymap:" << '\n'; - std::cout << "a => " << mymap.find('a')->second << '\n'; - std::cout << "c => " << mymap.find('c')->second << '\n'; - std::cout << "d => " << mymap.find('d')->second << '\n'; + std::cout << "a => " << mymap.find(VALT('a'))->second << '\n'; + std::cout << "c => " << mymap.find(VALT('c'))->second << '\n'; + std::cout << "d => " << mymap.find(VALT('d'))->second << '\n'; DELETE } @@ -434,14 +417,15 @@ TEST_M(tests_map_count) // title TITLE(cplusplus.com reference) - std::map mymap; - char c; + ft::map mymap; + T c; - mymap ['a']=101; - mymap ['c']=202; - mymap ['f']=303; + mymap [VALT('a')]=VALU(101); + mymap [VALT('c')]=VALU(202); + mymap [VALT('f')]=VALU(303); - for (c='a'; c<'h'; c++) + // to do this test with T as a 'string' or 'mystruct*' we should add overload + for (c=VALT('a'); c0) @@ -458,23 +442,21 @@ TEST_M(tests_map_lower_bound) // title TITLE(cplusplus.com reference) - std::map mymap; - std::map::iterator itlow,itup; + ft::map mymap; + typename ft::map::iterator itlow,itup; - mymap['a']=20; - mymap['b']=40; - mymap['c']=60; - mymap['d']=80; - mymap['e']=100; + mymap[VALT('a')]=VALU(20); + mymap[VALT('b')]=VALU(40); + mymap[VALT('c')]=VALU(60); + mymap[VALT('d')]=VALU(80); + mymap[VALT('e')]=VALU(100); - itlow=mymap.lower_bound ('b'); // itlow points to b - itup=mymap.upper_bound ('d'); // itup points to e (not d!) + itlow=mymap.lower_bound (VALT('b')); // itlow points to b + itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!) mymap.erase(itlow,itup); // erases [itlow,itup) - // print content: - for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) DELETE } @@ -484,23 +466,21 @@ TEST_M(tests_map_upper_bound) // title TITLE(cplusplus.com reference) - std::map mymap; - std::map::iterator itlow,itup; + ft::map mymap; + typename ft::map::iterator itlow,itup; - mymap['a']=20; - mymap['b']=40; - mymap['c']=60; - mymap['d']=80; - mymap['e']=100; + mymap[VALT('a')]=VALU(20); + mymap[VALT('b')]=VALU(40); + mymap[VALT('c')]=VALU(60); + mymap[VALT('d')]=VALU(80); + mymap[VALT('e')]=VALU(100); - itlow=mymap.lower_bound ('b'); // itlow points to b - itup=mymap.upper_bound ('d'); // itup points to e (not d!) + itlow=mymap.lower_bound (VALT('b')); // itlow points to b + itup=mymap.upper_bound (VALT('d')); // itup points to e (not d!) - mymap.erase(itlow,itup); // erases [itlow,itup) + mymap.erase(itlow,itup); // erases [itlow,itup) - // print content: - for (std::map::iterator it=mymap.begin(); it!=mymap.end(); ++it) - std::cout << it->first << " => " << it->second << '\n'; + PRINT(mymap) DELETE } @@ -510,14 +490,14 @@ TEST_M(tests_map_equal_range) // title TITLE(cplusplus.com reference) - std::map mymap; + ft::map mymap; - mymap['a']=10; - mymap['b']=20; - mymap['c']=30; + mymap[VALT('a')]=VALU(10); + mymap[VALT('b')]=VALU(20); + mymap[VALT('c')]=VALU(30); - std::pair::iterator,std::map::iterator> ret; - ret = mymap.equal_range('b'); + ft::pair::iterator,typename ft::map::iterator> ret; + ret = mymap.equal_range(VALT('b')); std::cout << "lower bound points to: "; std::cout << ret.first->first << " => " << ret.first->second << '\n'; @@ -534,14 +514,14 @@ TEST_M(tests_map_get_allocator) TITLE(cplusplus.com reference) int psize; - std::map mymap; - std::pair* p; + ft::map mymap; + ft::pair* p; // allocate an array of 5 elements using mymap's allocator: p=mymap.get_allocator().allocate(5); // assign some values to array - psize = sizeof(std::map::value_type)*5; + psize = sizeof(typename ft::map::value_type)*5; std::cout << "The allocated array has a size of " << psize << " bytes.\n"; @@ -555,29 +535,45 @@ TEST_M(tests_map_relational_operators) // title TITLE(cplusplus.com reference) - std::map alice{{1, 'a'}, {2, 'b'}, {3, 'c'}}; - std::map bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}}; - std::map eve{{1, 'a'}, {2, 'b'}, {3, 'c'}}; - - std::cout << std::boolalpha; - - // Compare non equal containers - std::cout << "alice == bob returns " << (alice == bob) << '\n'; - std::cout << "alice != bob returns " << (alice != bob) << '\n'; - std::cout << "alice < bob returns " << (alice < bob) << '\n'; - std::cout << "alice <= bob returns " << (alice <= bob) << '\n'; - std::cout << "alice > bob returns " << (alice > bob) << '\n'; - std::cout << "alice >= bob returns " << (alice >= bob) << '\n'; - - std::cout << '\n'; - - // Compare equal containers - std::cout << "alice == eve returns " << (alice == eve) << '\n'; - std::cout << "alice != eve returns " << (alice != eve) << '\n'; - std::cout << "alice < eve returns " << (alice < eve) << '\n'; - std::cout << "alice <= eve returns " << (alice <= eve) << '\n'; - std::cout << "alice > eve returns " << (alice > eve) << '\n'; - std::cout << "alice >= eve returns " << (alice >= eve) << '\n'; + ft::map alice; + ft::map bob; + ft::map eve; + (void)alice; + (void)bob; + (void)eve; + + alice[VALT(1)]=VALU('a'); + alice[VALT(2)]=VALU('b'); + alice[VALT(3)]=VALU('c'); + + bob[VALT(7)]=VALU('Z'); + bob[VALT(8)]=VALU('Y'); + bob[VALT(9)]=VALU('X'); + bob[VALT(10)]=VALU('W'); + + eve[VALT(1)]=VALU('a'); + eve[VALT(2)]=VALU('b'); + eve[VALT(3)]=VALU('c'); + + std::cout << std::boolalpha; + + // Compare non equal containers + std::cout << "alice == bob returns " << (alice == bob) << '\n'; + std::cout << "alice != bob returns " << (alice != bob) << '\n'; + std::cout << "alice < bob returns " << (alice < bob) << '\n'; + std::cout << "alice <= bob returns " << (alice <= bob) << '\n'; + std::cout << "alice > bob returns " << (alice > bob) << '\n'; + std::cout << "alice >= bob returns " << (alice >= bob) << '\n'; + + std::cout << '\n'; + + // Compare equal containers + std::cout << "alice == eve returns " << (alice == eve) << '\n'; + std::cout << "alice != eve returns " << (alice != eve) << '\n'; + std::cout << "alice < eve returns " << (alice < eve) << '\n'; + std::cout << "alice <= eve returns " << (alice <= eve) << '\n'; + std::cout << "alice > eve returns " << (alice > eve) << '\n'; + std::cout << "alice >= eve returns " << (alice >= eve) << '\n'; DELETE } @@ -588,33 +584,31 @@ TEST_M(tests_map_swap_non_member) // title TITLE(cplusplus.com reference) - std::map alice{{1, 'a'}, {2, 'b'}, {3, 'c'}}; - std::map bob{{7, 'Z'}, {8, 'Y'}, {9, 'X'}, {10, 'W'}}; - - auto print = [](std::pair& n) { - std::cout << " " << n.first << '(' << n.second << ')'; - }; - - // Print state before swap - std::cout << "alice:"; - std::for_each(alice.begin(), alice.end(), print); - std::cout << "\n" "bob :"; - std::for_each(bob.begin(), bob.end(), print); - std::cout << '\n'; - - std::cout << "-- SWAP\n"; - std::swap(alice, bob); - - // Print state after swap - std::cout << "alice:"; - std::for_each(alice.begin(), alice.end(), print); - std::cout << "\n" "bob :"; - std::for_each(bob.begin(), bob.end(), print); - std::cout << '\n'; + ft::map alice; + ft::map bob; + + alice[VALT(1)]=VALU('a'); + alice[VALT(2)]=VALU('b'); + alice[VALT(3)]=VALU('c'); + + bob[VALT(7)]=VALU('Z'); + bob[VALT(8)]=VALU('Y'); + bob[VALT(9)]=VALU('X'); + bob[VALT(10)]=VALU('W'); + + // Print state before swap + PRINT(alice) + PRINT(bob) + + std::cout << "-- SWAP\n"; + std::swap(alice, bob); + + // Print state after swap + PRINT(alice) + PRINT(bob) DELETE } -*/ #endif From 58d417742b8638bb4e97994bf9d61f5b9170759c Mon Sep 17 00:00:00 2001 From: hugogogo Date: Wed, 22 Jun 2022 00:22:04 +0200 Subject: [PATCH 41/53] map is bst --- Makefile | 17 +- headers/{bst.hpp => bak__bst.hpp} | 0 ...bst_iterator.hpp => bak__bst_iterator.hpp} | 0 headers/{bst_node.hpp => bak__bst_node.hpp} | 0 headers/bak__map.hpp | 207 ++++++ headers/map.hpp | 265 +++----- headers/map_iterator.hpp | 207 ++++++ headers/map_node.hpp | 50 ++ templates/bst.tpp | 16 +- templates/bst_bak.tpp | 628 ++++++++++++++++++ tests/main.cpp | 12 +- tests/tests_map.cpp | 4 + 12 files changed, 1228 insertions(+), 178 deletions(-) rename headers/{bst.hpp => bak__bst.hpp} (100%) rename headers/{bst_iterator.hpp => bak__bst_iterator.hpp} (100%) rename headers/{bst_node.hpp => bak__bst_node.hpp} (100%) create mode 100644 headers/bak__map.hpp create mode 100644 headers/map_iterator.hpp create mode 100644 headers/map_node.hpp create mode 100644 templates/bst_bak.tpp diff --git a/Makefile b/Makefile index 27780ad..a581397 100644 --- a/Makefile +++ b/Makefile @@ -67,18 +67,21 @@ HEADERS = colors.h \ equal.hpp \ lexicographical_compare.hpp \ pair.hpp \ - bst.hpp \ - bst_node.hpp \ - bst_iterator.hpp \ \ - vector.hpp \ - map.hpp + map.hpp \ + map_node.hpp \ + map_iterator.hpp \ + vector.hpp +# map.hpp +# bst.hpp +# bst_node.hpp +# bst_iterator.hpp D_TEMPLATES = ./templates TEMPLATES = bst.tpp \ \ - vector.tpp \ - map.tpp + vector.tpp +# map.tpp D_TESTS = ./tests/includes TESTS = main.hpp \ diff --git a/headers/bst.hpp b/headers/bak__bst.hpp similarity index 100% rename from headers/bst.hpp rename to headers/bak__bst.hpp diff --git a/headers/bst_iterator.hpp b/headers/bak__bst_iterator.hpp similarity index 100% rename from headers/bst_iterator.hpp rename to headers/bak__bst_iterator.hpp diff --git a/headers/bst_node.hpp b/headers/bak__bst_node.hpp similarity index 100% rename from headers/bst_node.hpp rename to headers/bak__bst_node.hpp diff --git a/headers/bak__map.hpp b/headers/bak__map.hpp new file mode 100644 index 0000000..76bea02 --- /dev/null +++ b/headers/bak__map.hpp @@ -0,0 +1,207 @@ + +#ifndef MAP_HPP +# define MAP_HPP + +# include "colors.h" +# include // std::allocator +# include // NULL, std::size_t, std::ptrdiff_t +# include // std::less, std::binary_function + +# include "pair.hpp" +# include "bst.hpp" + +namespace ft { + +template < + class Key, // map::key_type + class T, // map::mapped_type + class Compare = std::less, // map::key_compare + class Alloc = std::allocator< ft::pair > // map::allocator_type +> class map { + +public: + + typedef Key key_type; + typedef T mapped_type; + typedef pair value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef Compare key_compare; + typedef Alloc allocator_type; + +// typedef typename allocator_type::reference reference; +// typedef typename allocator_type::const_reference const_reference; +// typedef typename allocator_type::pointer pointer; +// typedef typename allocator_type::const_pointer const_pointer; + + typedef Bst bst_map; + + typedef typename bst_map::iterator iterator; + typedef typename bst_map::const_iterator const_iterator; + typedef typename bst_map::reverse_iterator reverse_iterator; + typedef typename bst_map::const_reverse_iterator const_reverse_iterator; + + + /**************** + * member class : + ****************/ + // https://en.cppreference.com/w/cpp/container/map/value_compare + // https://stackoverflow.com/questions/4571355/why-would-one-use-nested-classes-in-c + class value_compare : public std::binary_function { + + friend class map; + protected: + Compare comp; + value_compare(Compare c) : comp(c) {} + public: + bool operator() (const value_type& x, const value_type& y) const + { return comp(x.first, y.first); } + }; + + + /************ + * copliens : + ************/ +// constructors ------------------------------ + explicit map (const key_compare& comp = key_compare(), + const allocator_type& alloc = allocator_type()); + template + map (InputIterator first, InputIterator last, + const key_compare& comp = key_compare(), + const allocator_type& alloc = allocator_type()); + map (const map& x); +// destructor -------------------------------- + ~map(); +// operator= --------------------------------- + map& operator= (const map& x); + + + /************* + * iterators : + *************/ +// begin ------------------------------------- + iterator begin(); + const_iterator begin() const; +// end --------------------------------------- + iterator end(); + const_iterator end() const; +// rbegin ------------------------------------ + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; +// rend -------------------------------------- + reverse_iterator rend(); + const_reverse_iterator rend() const; + + + /************ + * capacity : + ************/ +// empty ------------------------------------- + bool empty() const; +// size -------------------------------------- + size_type size() const; +// max_size ---------------------------------- + size_type max_size() const; + + + /****************** + * element access : + ******************/ +// operator[] -------------------------------- + mapped_type & operator[] (const key_type& k); + + + /************* + * modifiers : + *************/ +// insert ------------------------------------ + pair insert (const value_type& val); + iterator insert (iterator position, const value_type& val); + template + void insert (InputIterator first, InputIterator last); +// erase ------------------------------------- + void erase (iterator position); + size_type erase (const key_type& k); + void erase (iterator first, iterator last); +// swap -------------------------------------- + void swap (map& x); +// clear ------------------------------------- + void clear(); + + + /************* + * observers : + *************/ +// key_comp ---------------------------------- + key_compare key_comp() const; +// value_comp -------------------------------- + value_compare value_comp() const; + + + /************** + * operations : + **************/ +// find -------------------------------------- + iterator find (const key_type& k); + const_iterator find (const key_type& k) const; +// count ------------------------------------- + size_type count (const key_type& k) const; +// lower_bound ------------------------------- + iterator lower_bound (const key_type& k); + const_iterator lower_bound (const key_type& k) const; +// upper_bound ------------------------------- + iterator upper_bound (const key_type& k); + const_iterator upper_bound (const key_type& k) const; +// equal_range ------------------------------- + pair equal_range (const key_type& k) const; + pair equal_range (const key_type& k); + + + /************* + * allocator : + *************/ +// get_allocator ----------------------------- + allocator_type get_allocator() const; + + // TMP non privat + bst_map _bst; +private: + + allocator_type _allocator; + key_compare _comp; + +}; + + + /************************ + * non-member functions : + ************************/ +// operator == ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator== + ( const std::map& lhs, const std::map& rhs ); +// operator != ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator!= + ( const std::map& lhs, const std::map& rhs ); +// operator < -------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator< + ( const std::map& lhs, const std::map& rhs ); +// operator <= ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator<= + ( const std::map& lhs, const std::map& rhs ); +// operator > -------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator> + ( const std::map& lhs, const std::map& rhs ); +// operator >= ------------------------------- +template< class K, class T, class Comp, class Alloc > bool operator>= + ( const std::map& lhs, const std::map& rhs ); +// swap (map) ----------------------------- +template< class Key, class T, class Compare, class Alloc > void swap + ( std::map& lhs, std::map& rhs ); + + +} // namespace ft + +# include "map.tpp" + +#endif + diff --git a/headers/map.hpp b/headers/map.hpp index 76bea02..9ab5e19 100644 --- a/headers/map.hpp +++ b/headers/map.hpp @@ -2,13 +2,18 @@ #ifndef MAP_HPP # define MAP_HPP -# include "colors.h" # include // std::allocator # include // NULL, std::size_t, std::ptrdiff_t +# include // max() # include // std::less, std::binary_function +# include "reverse_iterator.hpp" +# include "equal.hpp" +# include "lexicographical_compare.hpp" + # include "pair.hpp" -# include "bst.hpp" +# include "map_node.hpp" +# include "map_iterator.hpp" namespace ft { @@ -17,36 +22,27 @@ template < class T, // map::mapped_type class Compare = std::less, // map::key_compare class Alloc = std::allocator< ft::pair > // map::allocator_type -> class map { +> class map +{ + public: + typedef Key key_type; + typedef T mapped_type; + typedef pair value_type; + typedef Compare key_compare; + typedef Alloc allocator_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; -public: + // typedef typename Alloc::pointer pointer; + // typedef typename Alloc::const_pointer const_pointer; + // typedef typename Alloc::reference reference; + // typedef typename Alloc::const_reference const_reference; - typedef Key key_type; - typedef T mapped_type; - typedef pair value_type; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef Compare key_compare; - typedef Alloc allocator_type; + typedef map_iterator iterator; + typedef map_const_iterator const_iterator; + typedef ft::reverse_iterator reverse_iterator; + typedef ft::reverse_iterator const_reverse_iterator; -// typedef typename allocator_type::reference reference; -// typedef typename allocator_type::const_reference const_reference; -// typedef typename allocator_type::pointer pointer; -// typedef typename allocator_type::const_pointer const_pointer; - - typedef Bst bst_map; - - typedef typename bst_map::iterator iterator; - typedef typename bst_map::const_iterator const_iterator; - typedef typename bst_map::reverse_iterator reverse_iterator; - typedef typename bst_map::const_reverse_iterator const_reverse_iterator; - - - /**************** - * member class : - ****************/ - // https://en.cppreference.com/w/cpp/container/map/value_compare - // https://stackoverflow.com/questions/4571355/why-would-one-use-nested-classes-in-c class value_compare : public std::binary_function { friend class map; @@ -58,150 +54,105 @@ public: { return comp(x.first, y.first); } }; + // Member functions + explicit map(const Compare& comp = Compare(), const Alloc& alloc = Alloc() ); + template < typename InputIt > + map(InputIt first, InputIt last, const Compare& comp = Compare(), const Alloc& alloc = Alloc()); + map(const map& src); + ~map(); - /************ - * copliens : - ************/ -// constructors ------------------------------ - explicit map (const key_compare& comp = key_compare(), - const allocator_type& alloc = allocator_type()); - template - map (InputIterator first, InputIterator last, - const key_compare& comp = key_compare(), - const allocator_type& alloc = allocator_type()); - map (const map& x); -// destructor -------------------------------- - ~map(); -// operator= --------------------------------- - map& operator= (const map& x); + map& operator=(const map& rhs); + // Element access + T& operator[](const Key& key); - /************* - * iterators : - *************/ -// begin ------------------------------------- - iterator begin(); - const_iterator begin() const; -// end --------------------------------------- - iterator end(); - const_iterator end() const; -// rbegin ------------------------------------ - reverse_iterator rbegin(); - const_reverse_iterator rbegin() const; -// rend -------------------------------------- - reverse_iterator rend(); - const_reverse_iterator rend() const; + // Iterators + iterator begin(); + const_iterator begin() const; + iterator end(); + const_iterator end() const; + reverse_iterator rbegin(); + const_reverse_iterator rbegin() const; + reverse_iterator rend(); + const_reverse_iterator rend() const; + // Capacity + bool empty() const; + size_type size() const; + size_type max_size() const; - /************ - * capacity : - ************/ -// empty ------------------------------------- - bool empty() const; -// size -------------------------------------- - size_type size() const; -// max_size ---------------------------------- - size_type max_size() const; + // Modifiers + void clear(); + pair insert(const value_type& value); + iterator insert(iterator hint, const value_type& value); + template < typename InputIt > + void insert(InputIt first, InputIt last); + void erase(iterator pos); + void erase(iterator first, iterator last); + size_type erase(const Key& key); + void swap(map& other); + // Lookup + iterator find(const Key& key); + const_iterator find(const Key& key) const; + size_type count(const Key& key) const; - /****************** - * element access : - ******************/ -// operator[] -------------------------------- - mapped_type & operator[] (const key_type& k); + private: + size_type _size; + node* _root; + node_sentinel* _sentinel; + Compare _comp; + Alloc _allocator; + // TODO : rebind syntaxe pas clair. + typename Alloc::template rebind< node >::other _allocator_node; // Peu clair, verifier syntaxe + typename Alloc::template rebind< node_sentinel >::other _allocator_node_sentinel; // Peu clair, verifier syntaxe - /************* - * modifiers : - *************/ -// insert ------------------------------------ - pair insert (const value_type& val); - iterator insert (iterator position, const value_type& val); - template - void insert (InputIterator first, InputIterator last); -// erase ------------------------------------- - void erase (iterator position); - size_type erase (const key_type& k); - void erase (iterator first, iterator last); -// swap -------------------------------------- - void swap (map& x); -// clear ------------------------------------- - void clear(); + void _init_sentinel(); + pair _insert(const value_type& value); + node* _erase(iterator pos); + node* _subtree_shift(node* st_old, node* st_new); + // AVL Balancing + void _insert_rebalancing(node* n); + void _erase_rebalancing(node* n); - /************* - * observers : - *************/ -// key_comp ---------------------------------- - key_compare key_comp() const; -// value_comp -------------------------------- - value_compare value_comp() const; + short _compute_height(node* n); + short _bf(node* n); // balance factor + node* _rotate_left(node* n); + node* _rotate_right(node* n); + }; + // Non-member functions + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator==(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator!=(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator<(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator>(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator<=(const map& lhs, const map& rhs); + template < typename Key, typename T, typename Compare, typename Alloc > + bool operator>=(const map& lhs, const map& rhs); - /************** - * operations : - **************/ -// find -------------------------------------- - iterator find (const key_type& k); - const_iterator find (const key_type& k) const; -// count ------------------------------------- - size_type count (const key_type& k) const; -// lower_bound ------------------------------- - iterator lower_bound (const key_type& k); - const_iterator lower_bound (const key_type& k) const; -// upper_bound ------------------------------- - iterator upper_bound (const key_type& k); - const_iterator upper_bound (const key_type& k) const; -// equal_range ------------------------------- - pair equal_range (const key_type& k) const; - pair equal_range (const key_type& k); - - - /************* - * allocator : - *************/ -// get_allocator ----------------------------- - allocator_type get_allocator() const; - - // TMP non privat - bst_map _bst; -private: - - allocator_type _allocator; - key_compare _comp; - -}; - - - /************************ - * non-member functions : - ************************/ -// operator == ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator== - ( const std::map& lhs, const std::map& rhs ); -// operator != ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator!= - ( const std::map& lhs, const std::map& rhs ); -// operator < -------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator< - ( const std::map& lhs, const std::map& rhs ); -// operator <= ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator<= - ( const std::map& lhs, const std::map& rhs ); -// operator > -------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator> - ( const std::map& lhs, const std::map& rhs ); -// operator >= ------------------------------- -template< class K, class T, class Comp, class Alloc > bool operator>= - ( const std::map& lhs, const std::map& rhs ); -// swap (map) ----------------------------- -template< class Key, class T, class Compare, class Alloc > void swap - ( std::map& lhs, std::map& rhs ); - + template < typename Key, typename T, typename Compare, typename Alloc > + void swap(map& lhs, map& rhs); } // namespace ft -# include "map.tpp" +# include "bst.tpp" + +// https://en.wikipedia.org/wiki/Binary_search_tree +// https://en.wikipedia.org/wiki/AVL_tree + +// https://fr.wikipedia.org/wiki/Arbre_binaire_de_recherche +// https://fr.wikipedia.org/wiki/Arbre_AVL + +// https://visualgo.net/en/bst +// https://visualgo.net/en/bst?slide=14-8 // --> to 14-13 + #endif diff --git a/headers/map_iterator.hpp b/headers/map_iterator.hpp new file mode 100644 index 0000000..9a70567 --- /dev/null +++ b/headers/map_iterator.hpp @@ -0,0 +1,207 @@ +#ifndef MAP_ITERATOR_HPP +# define MAP_ITERATOR_HPP + +# include // NULL, ptrdiff_t +# include // iterator_tag + +# include "pair.hpp" +# include "map_node.hpp" + +namespace ft { + +template < + typename Key, + typename T, + typename Compare, + typename Allocator +> class map_iterator +{ + private: + typedef map_iterator Self; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef pair value_type; + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef value_type& reference; + + map_iterator() : _node(), _sentinel() {} + map_iterator(node* n, node_sentinel* sentinel) : _node(n), _sentinel(sentinel) {} + //map_iterator(const map_iterator& src) : _node(src._node), _sentinel(src._sentinel) {} //implicit + + reference operator*() const + { return _node->value; } + pointer operator->() const + { return &_node->value; } + + Self& operator++() + { + if (_node == NULL) + _node = _sentinel->child->min(); + else if (_node->right) + _node = _node->right->min(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->right) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self& operator--() + { + if (_node == NULL) + _node = _sentinel->child->max(); + else if (_node->left) + _node = _node->left->max(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->left) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self operator++(int) + { + //Self old(*this); + Self old = *this; + ++(*this); + return old; + } + + Self operator--(int) + { + //Self old(*this); + Self old = *this; + --(*this); + return old; + } + + node* getNode() + { return _node; } + const node* getNode() const + { return _node; } + const node_sentinel* getSentinel() const + { return _sentinel; } + + // TODO : friend Non-member functions syntaxe pas clair. + friend bool operator==(const Self &lhs, const Self &rhs) + { return lhs._node == rhs._node; } + friend bool operator!=(const Self &lhs, const Self &rhs) + { return !(lhs._node == rhs._node); } + + private: + node* _node; + node_sentinel* _sentinel; +}; + +template < + typename Key, + typename T, + typename Compare, + typename Allocator +> class map_const_iterator +{ + private: + typedef map_const_iterator Self; + + public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef pair value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type* pointer; + typedef const value_type& reference; + + map_const_iterator() : _node(), _sentinel() {} + map_const_iterator(const node* node, const node_sentinel* sentinel) : _node(node), _sentinel(sentinel) {} + //map_const_iterator(const map_const_iterator& src) : _node(src._node), _sentinel(src._sentinel) {} //implicit + map_const_iterator(const map_iterator& src) : _node(src.getNode()), _sentinel(src.getSentinel()) {} + + reference operator*() const + { return _node->value; } + pointer operator->() const + { return &_node->value; } + + Self& operator++() + { + if (_node == NULL) + _node = _sentinel->child->min(); + else if (_node->right) + _node = _node->right->min(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->right) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self& operator--() + { + if (_node == NULL) + _node = _sentinel->child->max(); + else if (_node->left) + _node = _node->left->max(); + else + { + node* up = _node->up; + while (up != NULL && _node == up->left) + { + _node = up; + up = up->up; + } + _node = up; + } + return *this; + } + + Self operator++(int) + { + //Self old(*this); + Self old = *this; + ++(*this); + return old; + } + + Self operator--(int) + { + //Self old(*this); + Self old = *this; + --(*this); + return old; + } + + node* getNode() const + { return _node; } + + friend bool operator==(const Self &lhs, const Self &rhs) + { return lhs._node == rhs._node; } + friend bool operator!=(const Self &lhs, const Self &rhs) + { return !(lhs._node == rhs._node); } + + private: + const node* _node; + const node_sentinel* _sentinel; +}; + +} // namespace ft + +#endif + diff --git a/headers/map_node.hpp b/headers/map_node.hpp new file mode 100644 index 0000000..3481ca9 --- /dev/null +++ b/headers/map_node.hpp @@ -0,0 +1,50 @@ + +#ifndef MAP_NODE_HPP +# define MAP_NODE_HPP + +# include // NULL + +namespace ft { + +template < typename ValueType > +struct node +{ + ValueType value; + node *up; + node *left; + node *right; + short height; + + node(const ValueType& val) : value(val), up(NULL), left(NULL), right(NULL), height(1) {} + + node* min() + { + node* n = this; + + while (n->left) + n = n->left; + return n; + } + + node* max() + { + node* n = this; + + while (n->right) + n = n->right; + return n; + } +}; + +template < typename ValueType > +struct node_sentinel +{ + node *child; + + node_sentinel() : child(NULL) {} +}; + +} // namespace ft + +#endif + diff --git a/templates/bst.tpp b/templates/bst.tpp index 0ade6c0..77a5f5a 100644 --- a/templates/bst.tpp +++ b/templates/bst.tpp @@ -1,6 +1,6 @@ #define BST_TEMPLATE template < typename Key, typename T, typename Compare, typename Allocator > -#define BST Bst +#define BST map namespace ft { @@ -10,7 +10,7 @@ namespace ft { BST_TEMPLATE BST:: - Bst(const Compare& comp, const Allocator& alloc) : + map(const Compare& comp, const Allocator& alloc) : _size(0), _root(NULL), _comp(comp), @@ -22,7 +22,7 @@ _allocator(alloc) BST_TEMPLATE template < typename InputIt > BST:: - Bst(InputIt first, InputIt last, const Compare& comp, const Allocator& alloc) : + map(InputIt first, InputIt last, const Compare& comp, const Allocator& alloc) : _size(0), _root(NULL), _comp(comp), @@ -34,7 +34,7 @@ _allocator(alloc) BST_TEMPLATE BST:: - Bst(const Bst& src) : + map(const map& src) : _size(0), _root(NULL), _comp(src._comp), @@ -46,7 +46,7 @@ _allocator(src._allocator) BST_TEMPLATE BST:: - ~Bst() + ~map() { clear(); _allocator_node_sentinel.destroy(_sentinel); @@ -55,11 +55,11 @@ BST:: BST_TEMPLATE BST& BST:: - operator=(const Bst& rhs) + operator=(const map& rhs) { if (this == &rhs) return (*this); - Bst new_bst(rhs.begin(), rhs.end()); + map new_bst(rhs.begin(), rhs.end()); swap(new_bst); return (*this); } @@ -241,7 +241,7 @@ typename BST::size_type BST:: BST_TEMPLATE void BST:: - swap(Bst& other) + swap(map& other) { node* tmp_root = _root; node_sentinel* tmp_sentinel = _sentinel; diff --git a/templates/bst_bak.tpp b/templates/bst_bak.tpp new file mode 100644 index 0000000..0ade6c0 --- /dev/null +++ b/templates/bst_bak.tpp @@ -0,0 +1,628 @@ + +#define BST_TEMPLATE template < typename Key, typename T, typename Compare, typename Allocator > +#define BST Bst + +namespace ft { + + + ////////////////////// + // Member functions // + +BST_TEMPLATE +BST:: + Bst(const Compare& comp, const Allocator& alloc) : +_size(0), +_root(NULL), +_comp(comp), +_allocator(alloc) +{ + _init_sentinel(); +} + +BST_TEMPLATE +template < typename InputIt > +BST:: + Bst(InputIt first, InputIt last, const Compare& comp, const Allocator& alloc) : +_size(0), +_root(NULL), +_comp(comp), +_allocator(alloc) +{ + _init_sentinel(); + insert(first, last); +} + +BST_TEMPLATE +BST:: + Bst(const Bst& src) : +_size(0), +_root(NULL), +_comp(src._comp), +_allocator(src._allocator) +{ + _init_sentinel(); + *this = src; +} + +BST_TEMPLATE +BST:: + ~Bst() +{ + clear(); + _allocator_node_sentinel.destroy(_sentinel); + _allocator_node_sentinel.deallocate(_sentinel, 1); +} + +BST_TEMPLATE +BST& BST:: + operator=(const Bst& rhs) +{ + if (this == &rhs) + return (*this); + Bst new_bst(rhs.begin(), rhs.end()); + swap(new_bst); + return (*this); +} + + + //////////////////// + // Element access // + +BST_TEMPLATE +T& BST:: + operator[](const Key& key) +{ + node* n = _root; + //node* prev = NULL; + + while (n) + { + //prev = n; + if (_comp(key, n->value.first)) + n = n->left; + else if (_comp(n->value.first, key)) + n = n->right; + else + return (n->value.second); + } + + // TODO : Call insert with hint (prev) + n = insert( ft::make_pair(key, mapped_type()) ).first.getNode(); + + return (n->value.second); +} + + + /////////////// + // Iterators // + +BST_TEMPLATE +typename BST::iterator BST:: + begin() +{ + if (_root) + return iterator(_root->min(), _sentinel); + else + return end(); +} + +BST_TEMPLATE +typename BST::const_iterator BST:: + begin() const +{ + if (_root) + return const_iterator(_root->min(), _sentinel); + else + return end(); +} + +BST_TEMPLATE +typename BST::iterator BST:: + end() { return iterator(NULL, _sentinel); } + +BST_TEMPLATE +typename BST::const_iterator BST:: + end() const { return const_iterator(NULL, _sentinel); } + +BST_TEMPLATE +typename BST::reverse_iterator BST:: + rbegin() { return reverse_iterator(end()); } + +BST_TEMPLATE +typename BST::const_reverse_iterator BST:: + rbegin() const { return const_reverse_iterator(end()); } + +BST_TEMPLATE +typename BST::reverse_iterator BST:: + rend() { return reverse_iterator(begin()); } + +BST_TEMPLATE +typename BST::const_reverse_iterator BST:: + rend() const { return const_reverse_iterator(begin()); } + + + ////////////// + // Capacity // + +BST_TEMPLATE +bool BST:: + empty() const { return (_size == 0); } + +BST_TEMPLATE +typename BST::size_type BST:: + size() const { return (_size); } + +BST_TEMPLATE +typename BST::size_type BST:: + max_size() const +{ + return ( _allocator_node.max_size() ); +} + + + /////////////// + // Modifiers // + +BST_TEMPLATE +void BST:: + clear() +{ + // TODO : optimisation jouable ? + erase(begin(), end()); + //_size = 0; +} + +BST_TEMPLATE +pair BST:: + insert(const value_type& value) +{ + pair ret; + + ret = _insert(value); + if (ret.second == true) + _insert_rebalancing(ret.first.getNode()->up); + return (ret); +} + +BST_TEMPLATE +typename BST::iterator BST:: + insert(iterator hint, const value_type& value) +{ + // TODO : optimise with hint + (void)hint; + return insert(value).first; +} + +BST_TEMPLATE +template < typename InputIt > +void BST:: + insert(InputIt first, InputIt last) +{ + //static int i = 0; // Debug + while (first != last) + { + insert(*first); + ++first; + //std::cout << "c|" << i << "\n"; + //++i; + } +} + +BST_TEMPLATE +void BST:: + erase(iterator pos) +{ + node* delete_point; + delete_point = _erase(pos); + _erase_rebalancing(delete_point); +} + +BST_TEMPLATE +void BST:: + erase(iterator first, iterator last) +{ + while (first != last) + erase(first++); +} + +BST_TEMPLATE +typename BST::size_type BST:: + erase(const Key& key) +{ + iterator pos = find(key); + if (pos == end()) + return (0); + else + { + erase(pos); + return (1); + } +} + +BST_TEMPLATE +void BST:: + swap(Bst& other) +{ + node* tmp_root = _root; + node_sentinel* tmp_sentinel = _sentinel; + size_type tmp_size = _size; + + _root = other._root; + _sentinel = other._sentinel; + _size = other._size; + + other._root = tmp_root; + other._sentinel = tmp_sentinel; + other._size = tmp_size; +} + + + //////////// + // Lookup // + +BST_TEMPLATE +typename BST::iterator BST:: + find(const Key& key) +{ + node* n = _root; + + while (n) + { + if (_comp(key, n->value.first)) + n = n->left; + else if (_comp(n->value.first, key)) + n = n->right; + else + return (iterator(n, _sentinel)); + } + return (end()); +} + +BST_TEMPLATE +typename BST::const_iterator BST:: + find(const Key& key) const +{ + node* n = _root; + + while (n) + { + if (_comp(key, n->value.first)) + n = n->left; + else if (_comp(n->value.first, key)) + n = n->right; + else + return (const_iterator(n, _sentinel)); + } + return (end()); +} + +BST_TEMPLATE +typename BST::size_type BST:: + count(const Key& key) const +{ + if (find(key) != end()) + return (1); + else + return (0); +} + + + /////////////////////// + // Private functions // + +BST_TEMPLATE +void BST:: + _init_sentinel() +{ + _sentinel = _allocator_node_sentinel.allocate(1); + _allocator_node_sentinel.construct(_sentinel, node_sentinel()); +} + +BST_TEMPLATE +pair BST:: + _insert(const value_type& value) +{ + node* n = _root; + node* prev = NULL; + + while (n) + { + prev = n; + if (_comp(value.first, n->value.first)) + n = n->left; + else if (_comp(n->value.first, value.first)) + n = n->right; + else + return ft::make_pair(iterator(n, _sentinel), false); + } + + n = _allocator_node.allocate(1); + _allocator_node.construct(n, node(value)); + if (_root == NULL) // if (_size == 0) + { + _root = n; + _sentinel->child = _root; + } + else if (_comp(value.first, prev->value.first)) + prev->left = n; + else + prev->right = n; + n->up = prev; + ++_size; + return ft::make_pair(iterator(n, _sentinel), true); +} + +BST_TEMPLATE +node* BST:: + _erase(iterator pos) +{ + node* n = pos.getNode(); + node* delete_point = NULL; + + if (n->left && n->right) // 2 child + { + node* next = n->right->min(); + + if (next->up != n) + { + _subtree_shift(next, next->right); + next->right = n->right; + next->right->up = next; + } + delete_point = _subtree_shift(n, next); + next->left = n->left; + next->left->up = next; + } + else if (!n->left && !n->right) // no child (leaf) + delete_point = _subtree_shift(n, NULL); // bug ? + else if (n->left) // 1 child + delete_point = _subtree_shift(n, n->left); + else if (n->right) // 1 child + delete_point = _subtree_shift(n, n->right); // bug ? + + _allocator_node.destroy(n); + _allocator_node.deallocate(n, 1); + --_size; + return (delete_point); +} + +BST_TEMPLATE +node* BST:: + _subtree_shift(node* st_old, node* st_new) +{ + node* p = st_old->up; + + if (st_old == _root) + { + _root = st_new; + _sentinel->child = _root; + } + else if (st_old == p->left) + p->left = st_new; + else + p->right = st_new; + + if (st_new == NULL) + return (p); // return deletion point + st_new->up = p; + return (st_new); // return deletion point +} + +BST_TEMPLATE +void BST:: + _insert_rebalancing(node* n) +{ + node* old_n; + node* parent = NULL; + + while (n) + { + n->height = _compute_height(n); + + if (_bf(n) > 1) // Left Heavy + { + parent = n->up; + if (_bf(n->left) < 0) // Left-Right Case (BF == -1) + n->left = _rotate_left(n->left); + // Left-Left Case + n = _rotate_right(n); + old_n = n->right; + } + else if (_bf(n) < -1) // Right Heavy + { + parent = n->up; + if (_bf(n->right) > 0) // Right-Left Case (BF == 1) + n->right = _rotate_right(n->right); + // Right-Right Case + n = _rotate_left(n); + old_n = n->left; + } + + if (parent) + { + if (parent->left == old_n) + parent->left = n; + else + parent->right = n; + break; + } + + n = n->up; + } + + while (n) + { + n->height = _compute_height(n); + n = n->up; + } +} + +BST_TEMPLATE +void BST:: + _erase_rebalancing(node* n) +{ + node* old_n; + node* parent = NULL; + + while (n) + { + n->height = _compute_height(n); + + if (_bf(n) > 1) // Left Heavy + { + parent = n->up; + if (_bf(n->left) < 0) // Left-Right Case (BF == -1) + n->left = _rotate_left(n->left); + // Left-Left Case + n = _rotate_right(n); + old_n = n->right; + } + else if (_bf(n) < -1) // Right Heavy + { + parent = n->up; + if (_bf(n->right) > 0) // Right-Left Case (BF == 1) + n->right = _rotate_right(n->right); + // Right-Right Case + n = _rotate_left(n); + old_n = n->left; + } + + if (parent) + { + if (parent->left == old_n) + parent->left = n; + else + parent->right = n; + parent = NULL; + } + + n = n->up; + } +} + +BST_TEMPLATE +short BST:: + _compute_height(node* n) +{ + if (n->left && n->right) + return std::max(n->left->height, n->right->height) + 1; + else if (n->left) + return n->left->height + 1; + else if (n->right) + return n->right->height + 1; + else + return 1; +} + +BST_TEMPLATE +short BST:: + _bf(node* n) // optimisation possible if assume n have at least one child ? +{ + if (n->left && n->right) + return n->left->height - n->right->height; + else if (n->left) + return n->left->height; + else if (n->right) + return (-(n->right->height)); + else + return 0; +} + +BST_TEMPLATE +node* BST:: + _rotate_left(node* n) // assume n->right != NULL +{ + node* ori_right = n->right; + + ori_right->up = n->up; + n->up = ori_right; + + n->right = ori_right->left; + if (n->right != NULL) + n->right->up = n; + ori_right->left = n; + + n->height = _compute_height(n); + ori_right->height = _compute_height(ori_right); + + if (n == _root) + { + _root = ori_right; + _sentinel->child = _root; + } + + return ori_right; // return new sub-tree root +} + +BST_TEMPLATE +node* BST:: + _rotate_right(node* n) // assume n->left != NULL +{ + node* ori_left = n->left; + + ori_left->up = n->up; + n->up = ori_left; + + n->left = ori_left->right; + if (n->left != NULL) + n->left->up = n; + ori_left->right = n; + + n->height = _compute_height(n); + ori_left->height = _compute_height(ori_left); + + if (n == _root) + { + _root = ori_left; + _sentinel->child = _root; + } + + return ori_left; // return new sub-tree root +} + + + ////////////////////////// + // Non-member functions // + +BST_TEMPLATE +bool operator==(const BST& lhs, const BST& rhs) +{ + if (lhs.size() != rhs.size()) + return false; + return ft::equal(lhs.begin(), lhs.end(), rhs.begin()); +} + +BST_TEMPLATE +bool operator!=(const BST& lhs, const BST& rhs) + { return !(lhs == rhs); } + + +BST_TEMPLATE +bool operator<(const BST& lhs, const BST& rhs) +{ + return ft::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); +} + +BST_TEMPLATE +bool operator>(const BST& lhs, const BST& rhs) + { return (rhs < lhs); } + +BST_TEMPLATE +bool operator<=(const BST& lhs, const BST& rhs) + { return !(lhs > rhs); } + +BST_TEMPLATE +bool operator>=(const BST& lhs, const BST& rhs) + { return !(lhs < rhs); } + + +BST_TEMPLATE +void swap(BST& lhs, BST& rhs) + { lhs.swap(rhs); } + + +} // namespace ft + +#undef BST +#undef BST_TEMPLATE + diff --git a/tests/main.cpp b/tests/main.cpp index 05fe950..b5696e7 100644 --- a/tests/main.cpp +++ b/tests/main.cpp @@ -49,14 +49,14 @@ int main() { tests_map_erase(); tests_map_swap(); tests_map_clear(); - tests_map_key_comp(); - tests_map_value_comp(); +// tests_map_key_comp(); +// tests_map_value_comp(); tests_map_find(); tests_map_count(); - tests_map_lower_bound(); - tests_map_upper_bound(); - tests_map_equal_range(); - tests_map_get_allocator(); +// tests_map_lower_bound(); +// tests_map_upper_bound(); +// tests_map_equal_range(); +// tests_map_get_allocator(); // tests_map_relational_operators(); tests_map_swap_non_member(); diff --git a/tests/tests_map.cpp b/tests/tests_map.cpp index 1472110..54373fc 100644 --- a/tests/tests_map.cpp +++ b/tests/tests_map.cpp @@ -336,6 +336,7 @@ TEST_M(tests_map_clear) DELETE } +/* TEST_M(tests_map_key_comp) { // title @@ -385,6 +386,7 @@ TEST_M(tests_map_value_comp) DELETE } +*/ TEST_M(tests_map_find) { @@ -437,6 +439,7 @@ TEST_M(tests_map_count) DELETE } +/* TEST_M(tests_map_lower_bound) { // title @@ -529,6 +532,7 @@ TEST_M(tests_map_get_allocator) DELETE } +*/ TEST_M(tests_map_relational_operators) { From 6617d6cdf59dee509bf97e627e2724d517549c52 Mon Sep 17 00:00:00 2001 From: hugogogo Date: Fri, 24 Jun 2022 02:23:53 +0200 Subject: [PATCH 42/53] stack almost good --- Makefile | 93 +-- containers_ft | Bin 0 -> 3535792 bytes headers/bak__bst.hpp | 187 +++-- headers/bak__map.hpp | 12 +- headers/map.hpp | 267 +++++--- headers/map_iterator.hpp | 31 +- headers/map_node.hpp | 24 +- headers/stack.hpp | 94 +++ templates/{bst_bak.tpp => bak__bst.tpp} | 145 ++-- templates/bak__map.tpp | 268 ++++++++ templates/bst.tpp | 628 ----------------- templates/map.tpp | 527 ++++++++++++--- tests/includes/main.hpp | 3 +- tests/includes/tests_mutant_stack.hpp | 22 + tests/includes/tests_utils.hpp | 36 +- tests/main.cpp | 39 +- tests/main_map_1.cpp | 741 ++++++++++++++++++++ tests/main_map_2.cpp | 862 ++++++++++++++++++++++++ tests/main_stack_1.cpp | 187 +++++ tests/test.sh | 10 +- tests/tests_map.cpp | 9 - tests/tests_stack.cpp | 29 + tests/tests_vector.cpp | 4 - 23 files changed, 3137 insertions(+), 1081 deletions(-) create mode 100755 containers_ft create mode 100644 headers/stack.hpp rename templates/{bst_bak.tpp => bak__bst.tpp} (84%) create mode 100644 templates/bak__map.tpp delete mode 100644 templates/bst.tpp create mode 100644 tests/includes/tests_mutant_stack.hpp create mode 100644 tests/main_map_1.cpp create mode 100644 tests/main_map_2.cpp create mode 100644 tests/main_stack_1.cpp create mode 100644 tests/tests_stack.cpp diff --git a/Makefile b/Makefile index a581397..10bd639 100644 --- a/Makefile +++ b/Makefile @@ -31,6 +31,8 @@ RESET = "\e[0m" # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # NAME = containers +NAME_FT = containers_ft +NAME_STL = containers_stl CC = g++ EXT = cpp @@ -39,6 +41,11 @@ CFLAGS = -Wall -Wextra -Werror $(INCLUDES) CFLAGS += -std=c++98 CFLAGS += -g3 +CFLAGS_STL = -Wall -Wextra -Werror $(INCLUDES) +CFLAGS_STL += -D STL +CFLAGS_STL += -std=c++98 +CFLAGS_STL += -g3 + VPATH = $(D_SRCS) LIBS = @@ -52,14 +59,20 @@ INCLUDES = -I$(D_HEADERS) \ D_SRCS = ./tests #SRCS = main42.cpp -SRCS = main.cpp \ - tests_definitions.cpp \ - \ - tests_vector.cpp \ - tests_map.cpp +#SRCS = main_map_1.cpp +#SRCS = main_map_2.cpp +SRCS = main_stack_1.cpp +#SRCS = \ +# main.cpp \ +# tests_definitions.cpp \ +# \ +# tests_vector.cpp \ +# tests_map.cpp \ +# tests_stack.cpp D_HEADERS = ./headers -HEADERS = colors.h \ +HEADERS = \ + colors.h \ \ enable_if.hpp \ iterator_traits.hpp \ @@ -71,30 +84,23 @@ HEADERS = colors.h \ map.hpp \ map_node.hpp \ map_iterator.hpp \ - vector.hpp -# map.hpp -# bst.hpp -# bst_node.hpp -# bst_iterator.hpp + vector.hpp \ + stack.hpp D_TEMPLATES = ./templates -TEMPLATES = bst.tpp \ - \ - vector.tpp -# map.tpp +TEMPLATES = \ + vector.tpp \ + map.tpp D_TESTS = ./tests/includes -TESTS = main.hpp \ +TESTS = \ + main.hpp \ tests_utils.hpp -D_OBJS = builds -OBJS = $(SRCS:%.$(EXT)=$(D_OBJS)/%.o) - -ifeq "$(D_OBJS)" "." - RM_OBJS = rm -f $(OBJS) -else - RM_OBJS = rm -rf $(D_OBJS) -endif +D_OBJS_FT = builds_ft +OBJS_FT = $(SRCS:%.$(EXT)=$(D_OBJS_FT)/%.o) +D_OBJS_STL = builds_stl +OBJS_STL = $(SRCS:%.$(EXT)=$(D_OBJS_STL)/%.o) # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # @@ -103,37 +109,42 @@ endif # . @recipe (silent) . $^ : all prerequisites # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # -all: $(NAME) +all: $(NAME_FT) $(NAME_STL) -stl: CFLAGS += -D STL -stl: re -ft: re +stl: $(NAME_STL) +ft: $(NAME_FT) -leakstl: CFLAGS += -D STL -leakstl: fclean leaks -leakft: fclean leaks - -$(D_OBJS)/%.o: %.$(EXT) | $(D_OBJS) +$(D_OBJS_FT)/%.o: %.$(EXT) | $(D_OBJS_FT) @echo $(CYAN)"compilation " $@ $(RESET) @$(CC) $(CFLAGS) -c $< -o $@ +$(D_OBJS_STL)/%.o: %.$(EXT) | $(D_OBJS_STL) + @echo $(CYAN)"compilation -D STL" $@ $(RESET) + @$(CC) $(CFLAGS) -D STL -c $< -o $@ -$(D_OBJS): +$(D_OBJS_FT) $(D_OBJS_STL): mkdir $@ $(OBJS): $(F_INCLUDES) -$(NAME): $(OBJS) - @echo $(CYAN)"linkage (link objects.o) :"$(RESET) - $(CC) $(OBJS) -o $@ $(LIBS) +# https://stackoverflow.com/questions/19259108/makefile-same-rule-for-multiple-targets +$(NAME_FT): $(OBJS_FT) +$(NAME_STL): $(OBJS_STL) +$(NAME_FT) $(NAME_STL): + @echo $(CYAN)"linkage (link objects.o)"$(RESET) + @$(CC) $^ -o $@ $(LIBS) -leaks: $(NAME) - valgrind --leak-check=full --show-leak-kinds=all ./$(NAME) +leaks: leaksft +leaksft: $(NAME_FT) + valgrind --leak-check=full --show-leak-kinds=all ./$< +leakstl: $(NAME_STL) + valgrind --leak-check=full --show-leak-kinds=all ./$< clean: - $(RM_OBJS) + rm -rf $(D_OBJS_FT) + rm -rf $(D_OBJS_STL) fclean: clean - rm -f $(NAME) + rm -f $(NAME_FT) $(NAME_STL) re: fclean all diff --git a/containers_ft b/containers_ft new file mode 100755 index 0000000000000000000000000000000000000000..752db1ad22f51f3bfd3fba89b3aa4c8aabe39a88 GIT binary patch literal 3535792 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≈JNwT`+eqY7?ZZf6m57zlslpn84XDG;^ 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

E*t+(KzhLV zzm-D8@t*@(MjdX&|7;2s$N#Y)Yy2M${e|(5 z^5?}rCVlI{>Y`2KmdxKb|s?LkVR(rW;<&F1duK9ZSdm_gNnU#s9t(DvtkefUNO968a0{ALY-B ze@y!NjsGtC_yzR;d!zP}@xKp#4=VnH;OB||2}6m0x?CpywKR->1jT^yPvL_2f0Adg zlJoyRfZ%}v{D())0CgbS(C{DRFEjtAGiBnRHQi7A@1^V^$Nxhpp^V3L!;9G^3vg#_ znfTAJJ_d^a6Dd?2|KmW`_&*W)3*#T<&x?Od`udIkDjcc!BI18f)Sk`%$0DU+HMseI zEdDv>|Ko=e|8%)b{F9~ge+0#V@lWA`_&<-=V5V_^G|lRa!!b|Y7SW!xozim8mcUDpm090{0g}m zIC4XJb7)W(8#QUCG7)en$DAW+a83Gse!@| z1*Q*;4KOJS7itx?yLTu7)8VG><7wczgIGo3q?U#062QF;>B7$i+BMTTe-7$sW0Kh@ z+yT!2Zr~5q#;xv$MQVfExW$Q$X(sK}x>T^i7wzQJ-)K3ST@>YDI^5c=!Md8-xW;8H zSVyXjtDV@GX0joDuvV0pgTLe_W~0GHVT0*xjv6zSkLWEsFFn$<_`r(Hi?U>A^hn85 zT*_Y5eudq9v({*3PYcTI2uQOmSf!$(A$_jX8#Os{*zgB&eT%*{ER%NCtdm{Dx64V8 z4NPynGkxFxRx^9;E}D0uv+a4D+AQy=*(06am}b(=Qe56P%_$dgvn0rkrgy9}-RvV~ zc2i@Ic6Km(yPDm_>GpjnH%oCj+suw~5jRVMY-M_@o#|$~%xtT*!3bvuv(Kv8jhx#Fp z&5|Iyn%;1Eshj=S%s%o>ZQI12<~nC5Ex)3c4{;XWN=DKx zGl#5hmdCn?TP8u~n(EQcbjv?5%il6~jkA-MuTsm~Ijb?vq+4bVX|iHfyNFvRLH04# zBb@1$XPD&$J7}4!oSn3sQp>}g)tF||Ei;E~XqGEn#4VE`PnhbykE7s~J^(vW80*L& z`#%;>B%5W|#IJ7I2EVZI=7hEIJ=m)G$aWQmRyfq;`1AI5XBh_-r9w!{Gu+@Np`xR#BK73{+Qa9+I8XZ zOE@c9So>MU;t5nw*;DStq6l||@vw&yo-_ikE}PIrCGu?}w1dzALU$^w*OYZe*Oav% zlpWV0E5XB&!y0NoYpm6#FSxI)N{hlf$509==#_oYH|-Qe3(uoWNy^J295I8BJ@9}9 z?2|3cr7jTQ4oY#GNpye!zd%@t5;>HbryMgA+CfC|YLT6#8rO~c)jHrfN;$O^muZ02 zdQi6Npv?Ls56ae69+WwJWTjMVnT9{evP>y;|5>s;42SaNsY;XwbuhJ0xEkOyLggsE zzjN*FpOClu;w-tme%)`)@Bq~GzU;Xp;22Ls%~~`7WGP+vH@Z?W*`SUfNe^2BU zmIoEpm%$l_PWRF7kIPK|7+2k8r+&P~)V@q_Nqu$jAK|AL(;>9XjkWJ0bKGDh zpD%VLW4<*6JmvOnFdCM|Q?g{S2U_791LG;DQMe?Y^1$=x!sGMmil=md<_*;;XTG2k z4UVT=Y&o!Mj`5T$5;+=VtmeqWQ^si~Uwl*8hzhNrB6+=i!2JdA77a3P>ARQFNh zmWUH|u`$hLF`n`<4Hn}mjXA2r)rOPM*s=^5Z$o+`*JZ2JHHz;yT+x#B4=9Lg%|IGtljs zVSwrIH6X=P&Qe`3xs2f{$0@P!ljKEs%0_0O(=)>W)8U&yil?lry5esFtjZZ z{4jYDp7P*xT1D*%15Ag{lPjL`3)S_I%UGD+pv1z@lb6C%#+!{+&yPYd9X=7HkvdM* z#h(bmjG;nCEAe*E*qCOrB%bmv=VpmJ*tdjb4e9G#odxR)O1##IjcF!J z;wg=0qrpXCgXzW`H8vFDDK~7P^ZXeu?aP1&Pno-=vZpya>Y|$E8eROJ>+}+M%DSU8 z>tq-4H2?|n8`E3wOg9_hDf=0FqO*h9xoY-Erch?^xrUNXJa&UCX8o-)zcBb*(~-lS$Xa(W3odfjYy6B6jmQLJwihtlBRu8B&9y4poNYcCs_}DO?cV3C5_rle zbF0Ngyb(x{mrZrEGrcw8uiX%Dq;s87|_MNs!}B^)zR?2!D6lW(bU#gZ*cUB2JWhb*-?;>uQ1bNF;PjseRj_{Pp#;$XA((>JE`4DH7z*8Qv zVvThXw@iZk&{U6hrdy8ily|?XWv+2{(()v=yq&X3;3;Fxaeq^d+Jf#)rOEhmZJY|>P#uLeA**fv7TfTx{ zW$=`WCy}ifPg#sDveJ0Uv*eV-Q|3Gk&fxKsODT?_HLO#*<*a-X@suVMJc*~&VRjv@ zr@0>O4fx2pFQbf(kNiM?l*LD0{*5kyVtiz`g-XEcD#Aw|Hi`c6k+Xs46t0=-;``jW zcI?yj@=)-RUCe_XxMcXqwMOUy!SIm{jDV$dgpZs}!sodS#gAP_>i@1&vfc!b7`;}QHZNIb&wu@ZqtSiZJF;}LOY;1T>$j7Kc^AH^f~ zKqZyMBg!?^4Q#3+R3bWWk$k`Hu5SzhkJ#`l7{^NE5g&aSEaDMoZk)g)dayOaF2_fu zOE=Jcq(4zO;1L}dP4NDFI|r40UqhD};}J@$11%a?aKF_G_Nrn7@Q60%Sl4nm9-*{N z5;+>AOC=nSXl15X|3otdc!YBP42}4BD1b}mV>`v{#OG{x+>ip8w|rFcxOq6@kldgov^90)!gbVj(W_buqg@UzP$gU-Novf6nwUM8 zY^hARFoiBCfb!T8UJI+SAvRYR3Z|2|oR|8o7MPTeUr`sTV;gg*5-yM=_iUiGFd}Bp zC0o*P&1)eA!aRjo_6#m4xYDvGYhfeLi{&Gds21us7nqbEnG2OJhgzUYxImJ8&0MI6 z*>lO36%sB~gJ2KkuW?*i9W(glKh%ZKe5OfaW@2zIX;aFTOs2WP=_Ph`m_G!v4^_=yp+f zL9OtDB-zBg=!)5M$(DbB?p}1!3w<=(4)?myM{^zZ;#tp&j}ah=uM<#zs0;p*xBjSg z(cz--f?DAPNz%NY)R0%vlN%HW_F^BxLFe91JhgQOg9^0 zJZBp_1HV|PgsFQyNH`5K`t=8HO_Ri5ytb$x*95@oE^+wqh_~q zIzFO?q?@Is8PS9N-0nn^cHae3J^_k9$N z<8GD&xx)1JIx{k>GIEA7rGV)e&-?3WRrEO9d@_vZuX=LjHD@)ZnRK_9L-sYdx?IHF zB0-j!>P}~RZA2K)G-G!-J85}M?CD`_bXKD#-7<5?lUA%Y7jerZ$aGWP>P)vBVLYE! zX_;G`owWRzmiZ=UHKv(#%giBlX1U2l+%gHWqFHWmrdy6Mo=eQ~3}+`Ti(07>vi@0SHBx9;4JJT&k7|-g)u6K6Q@{MZwyUxPY1WC8d9CD0Vu5%H$Oo9wI z)hTDX zyTg1L2U60BU)^#pegWg*BB1ch%^z~($uZVT+UFqul`)=A){fz5jYl5CxzogCPA z7O-{llnU&|0=70Dq!nW;O#ZN+}|i*>lpoXVCSP@BOx5k0;KcB zs3}VzW@x5nxg!W57hA4duE{469y??00FRAi3~i6eyT30%e55zvWBb2__;7q|H~mo- zA3L9)gH4_v`lAuB+K=$Dqm1w`#K&HGS$&N0v7ODOu7HotF^L!-Tb~l26CZ0qB=eE} zH#k4U_LqL~v3*`m;6wo*I~G*L8=;*JspF3U@v#HqEbX!fe+-0=rDiRu9`MW#zqUe* z%s!Gd4o96Ht;Er~6fTNty?Gfvt`cxE14{D0M^~R3?D?HB2#i7EW&D0QDhKt7^E*58 z$Kdd?O3TMeZIh1}nc3-WgT>3=MSp(+XUsXjg3)R#or+j$`_}PoAVx%sOpZ$s~;%7UomcY;Iv4SgspWR5| zfS)Dbk9y$0(51%snGT5^phaUg@Ut`DR*8mip2u=HepbU#@`^+boafOTj-QR9z&OoR zfS)PnusCaUo(H+@JWu;EsIugpk?6N7r_=#sFmCVs=vE z=i9Oz?>Vtilf}n+b~GD3E{9_hOv48C(S~AMmz#}l7qgQ+`>BnWoYeE}TpfiSU`rA{#$ZJrr6n1&7N zqYXu;7JNtRs@28pe9whygNIKd8%#D7o$p!IY;bPn?ZGr`P#4Ih2EG*q}bzIG$1ZF+g9m`7{?ZnCZc5BmI`lPFv%>!L8jG|W&X&1eK~ zYi3d|W)Upgur$QxqE=zDQubm^!7T_%|=Mj>sA@!>|l19ntjXZfD4gyvlN$|&1|=e zxLFcpvFYV>Uwv}35fbzRV|O|`nEjcWUF7t}G?Q+Y;6E{n7NtxMZ7jd&B$VaBP$(e38LV_+Zc7wBn+4a=yWljgm zhoqaOxIAYCn&u*ImIS%P^iFYRWL9P5WMfV)U^)^cpMAiGGqJm&@BdE5*dliRq+s*H z-C_>e&D^SU<@{XxaIn!$+LV`{+_E=|IZ5RgiJ4`Ve(tA1!2mz9AnK`7xidEwx zZkYr*%T$kYrdy7XprxN`nX8?hwA`SUH+2?9ek9#8bI5*XxynV{G70jbsjhUUTaJ*R z^Nd~L?4;#;)pEi1fLmq`dD@EA>xiLSCP6MT)#6OI93ep!#_n-;((;LF`88(&@k7!r zGlz^f%Uv$wmPwG6O?9U;-ExEkUHXaEb^^eUBkap+dA{ca;)kSLR(!wPl()HvTP8uW zrn=Rc@(6Gv8!&21@pB_!H5TC+TN~kDh-cjKf%+KZ8LOB}T>;NXn?#Ifyh+06#54X^ zo%dPq?}>GMz%#x9D!K(Oy*s3uKL*4zz8q(1m$mp~AUtD0EMr5*GO}YU@eUT=p4qFi z@C~G);ul{*s0RvYQ38a(608?_vN@{rb>3eqS%M|5%a(c1DN&qgZ~fR8Mq0u+z0$}0M`%S89ND6!p% zc8iLAawRGOF*iBc479l%3^1L|Q5_5@Ix$Ig-R&~beJ)CDb)voUlS%Imt&ssHWfe2f z;&L#+bT&tIFrd)HFx7Q~%UGB$S%t-FcA~xSW1qH7g+m{T4&MBM)>4y;!UogX95up* z;u1eqb(g!0MQVc*8=PqG``E{2VjDZL9N#h z%+|PwnF}