/ft_containers

Implementation of some STL containers (vector, map, stack) and some templates/helper classes (iterators_traits, reverse_iterator, enable_if, is_integral, equal, lexicographical compare, pair, make_pair)

Primary LanguageC++

[Project aim / subject]

Dans ce projet, vous allez devoir ré-implémenter les différents containers de la C++ STL (standard template library).

Pour chaque container, vous devez rendre des fichiers de classe nommés correctement.
Vous utiliserez le namespace ft, et vos containers seront appellés à l’aide de ft : :.
Vous devez respecter la structure de votre container de reference.
N’implementez que les élements présents.
Nous vous rapellons que vous codez en C++98, donc toutes les nouvelles fonctions des containers NE DOIVENT PAS être implémentées. Vous devez par contre implémenter les anciennes (même deprecated).

Implémentez les containers suivants, et rendez les fichiers .hpp nécessaires.
Vous devez produire un binaire avec uniquement vos conteneurs et un autre avec le même test avec les conteneurs STL.
Comparer les sorties et le temps (vous pouvez être jusqu’à 20 fois plus lent).
Les fonctions membres, les non-membres et les overloads sont attendues.
respectez le nommage, faites attention aux détails.
Vous devez utiliser std::allocator.
Vous devez justifier votre structure de données interne pour chaque conteneur
(utiliser un simple tableau pour une map n’est pas acceptable).
Si le conteneur a un système d’itérateur, vous devez l’implémenter.
• iterators_traits,
• reverse_iterator,
• enable_if,
• is_integral,
• equal, • lexicographical compare,
• std::pair,
• std::make_pair
doivent être réimplémenté.
Vous pouvez utiliser https://www.cplusplus.com/ et https://cppreference.com/ comme références.
Vous ne pouvez pas implémenter plus de fonctions publiques que celles proposées dans les conteneurs standard. Tout le reste doit être privé ou protégé.
Chaque fonction/variable publique doit être justifiée.
Pour les overloads non-membres, le mot-clé friend est autorisé. Chaque utilisation de friend doit être justifiée et sera vérifiée lors de l’évaluation.

Vous devez rendre les containers suivants et leur fonctions associés :
• Vector
• Map
• Stack

Pour votre implémentation vectorielle, il n’est pas obligatoire de coder la spécialisation vector< bool >.
Votre pile utilisera votre classe vectorielle comme conteneur sous-jacent par défaut,
il doit toujours être compatible avec d’autres conteneurs comme celui de STL.
Les conteneurs STL sont interdits.
Vous êtes autorisé à utiliser la bibliothèque STD

[Links]

libstdc++

iterator :

vector :

Docs / refs :

Iterators

Allocators

Vector

Stack

Map

Sources / Useful / various :

Notes

std::allocator
Allocators are classes that define memory models to be used by some parts of the Standard Library, and most specifically, by STL containers.

[Pointer const recap]

  • A non-const pointer can be assigned another address to change what it is pointing at

  • A const pointer always points to the same address, and this address can not be changed.

  • A pointer to a non-const value can change the value it is pointing to. These can not point to a const value.

  • A pointer to a const value treats the value as const when accessed through the pointer, and thus can not change the value it is pointing to. These can be pointed to const or non-const l-values (but not r-values, which don’t have an address)

  • The pointer’s type defines the type of the object being pointed at.
    So a const in the type means the pointer is pointing at a const value.

  • A const after the asterisk means the pointer itself is const and it can not be assigned a new address.

[Lvalue] An object reference. You can take the address of an lvalue, but you cannot take the address of an rvalue. The lefthand operand of the built-in assignment operator must be a non-const lvalue (hence the l in lvalue).

[Rvalue] A value that does not necessarily have any storage or address. An rvalue of fundamental type can appear only on the right side of an assignment (hence the R in Rvalue). An lvalue can be implicitly converted to an rvalue, but not the other way around.

Keywords :

[iterator_traits] Iterator traits allows algorithms to access information about a particular iterator in a uniform way to avoid re-implement of all iterators for each specific case, when it needs to traverse different style of containers. For example, Finding elements in std::list is O(n) complexity whereas in std::vector the random access to an element is O(1) complexity (given the index position). It is better for an algorithm to know that the container can be traversed using += operator (Random Access), or only ++ operator (Forward), to choose what is the better choice to reduce the complexity of the algorithm that is computed.

The iterator traits are the following ones:

  • difference_type:
    • the type for representing iterator distances
    • The type of iterator difference p2 - p1.
  • value_type:
    • the type of the value that iterator points
  • pointer:
    • the pointer value that iterator points
    • usually value_type*
  • reference:
    • the reference value that iterator points
    • usually value_type&
  • iterator category:
    • Identifies the iterator concept modeled by the iterator.

The traits also improve the efficiency of algorithms by making use of knowledge about basic iterator categories provided by the iterator_category member. An algorithm can use this "tag" to select the most efficient implementation an iterator is capable of handling without compromising the flexibility to deal with a variety of iterator types. (see [distance] and [advance] functions in utils/iterators/ft_iterators_traits.hpp who illustrate this)

[specializations] The iterator_traits class template is specialized for simple pointers or pointers to const. These specializations lets you use a pointer as a random access iterator.

[tags] Empty struct to identifies the iterator concept modeled by the iterator.

    struct input_iterator_tag {};
    struct output_iterator_tag {};
    struct forward_iterator_tag : input_iterator_tag {};
    struct bidirectional_iterator_tag : forward_iterator_tag {};
    struct random_access_iterator_tag : bidirectional_iterator_tag {};

explicit
The explicit keyword in C++ is used to mark constructors or function to not implicitly convert arguments types.

friend
A friend function of a class is defined outside that class' scope but it has the right to access all private and protected members of the class. Even though the prototypes for friend functions appear in the class definition, friends are not member functions. A friend can be a function, function template, or member function, or a class or class template, in which case the entire class and all of its members are friends.

[typeid] wip [typename] wip [class] wip [typedef] wip [virtual] wip [static] wip

cv-qualified A const or volatile qualifier, or both (in any order). c-v qualified means const and volatile ex :

// non cv_qualified 
int first; 
char *second; 

// cv-qualified 
const int third; 
volatile char * fourth; 

The const and volatile specifiers are optional. You can use either one, neither, or both in any order. The const and volatile keywords can be used in other parts of a declaration, so they are often referred to by the more general term qualifiers; for brevity, they are often referred to as cv-qualifiers.

[const] Denotes an object that cannot be modified. A const object cannot ordinarily be the target of an assignment. You cannot call a non- const member function of a const object.

[volatile] Denotes an object whose value might change unexpectedly. The compiler is prevented from performing optimizations that depend on the value not changing. For example, a variable that is tied to a hardware register should be volatile .

[SFINAE] Substitution Failure Is Not An Error. When the compiler looks for candidate functions for overload resolution, all function templates with the desired name are initially considered.
If the compiler cannot generate a template instance to match the function call’s arguments, that function template is not considered. That is, failure to substitute the arguments is not an error.

[enable_if] [is_integral] [lexicographical_compare]

BinaryPredicate forward declarations

STL LEAK / Issues :

    std::map<char, int, std::equal_to<char> > tmap;
    tmap['a'] = 42;
    tmap['a'] = 42;
    tmap['a'] = 42;
    tmap['a'] = 42;

Multiple key can work if :

    std::map<char, int, std::equal_to<char> > tmap;
	tmap.insert(std::make_pair('a', 84));
	tmap.insert(std::make_pair('a', 84));
	tmap.insert(std::make_pair('a', 84));
	tmap.insert(std::make_pair('a', 84));

In case of same multiple key count() dosn't work (return 0 even if there is the key)

	std::cout << "COUNT =" << tmap.count('a') << std::endl;

In case of same multiple key erase() remove nothing

	std::cout << "COUNT =" << tmap.count('a') << std::endl;

STL return : 13 (carriage return, CR, \r, ^M) when end() reached

TESTEURS :

https://github.com/mli42/containers_test https://github.com/mamoussa405/ft_containers_tests