Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ set(APP_SOURCES
"src/patterns/creational/AbstractFactory.cpp"
"src/patterns/creational/Builder.cpp"
"src/patterns/creational/Prototype.cpp"
## Container
"src/core/datatypes/container/sequence/Array.cpp"
"src/core/datatypes/container/sequence/Vector.cpp"
"src/core/datatypes/container/unordered/UnorderedMap.cpp"
)

# Test files
Expand Down
27 changes: 18 additions & 9 deletions src/core/basics/InitializeVariable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,24 @@ struct Foo {
void initialize_variable() {
cout << "\n--- Variable Initialization Examples ---\n";
// There are there common ways to intialize a variable
// * Default
// * 1) Default-initialization
[[maybe_unused]] int initDefaultVar;
[[maybe_unused]] Foo initDefaultObj;

// * Traditional initialization
// * Copy-init: Type var = value;
[[maybe_unused]] unsigned char* c = new unsigned char;
*c = 0xF; // actual init at this point for c
delete c;

// * 2) Value-initialization
[[maybe_unused]] int initValueVar1();
[[maybe_unused]] int initValueVar2{};

// * 3) direct-init: Type var(value);
[[maybe_unused]] Foo directInitObj(4); // call Foo(int)
[[maybe_unused]] Foo directInitObj2(
4.3); // look for constructor -> implicit 4.3(float) -> 4(int) -> call Foo(int) ->

// * 4) Copy-init: Type var = other;
// 1. Compiler tries to convert the value to a temporary Foo.
// 2. If the constructor is explicit, implicit conversion is blocked -> compilation error.
// 3. Otherwise, a temporary Foo is created and then copied/moved into the variable.
Expand All @@ -43,13 +55,10 @@ void initialize_variable() {
// Foo copyInitObjError = 2.3; // ERROR: implicit conversion blocked by explicit constructor
// We can explicitly prevent certain conversions using = delete or using {}

// * direct-init: Type var(value);
[[maybe_unused]] Foo directInitObj(4); // call Foo(int)
[[maybe_unused]] Foo directInitObj2(
4.3); // look for constructor -> implicit 4.3(float) -> 4(int) -> call Foo(int) ->

// * Brace init
// * 5) List-initialization (Brace init)
// calls the constructor directly without allowing implicit conversions.
[[maybe_unused]] Foo braceInit{3};
// Foo braceInit2{3.3}; // ERORR => Prefer this way
[[maybe_unused]] int ar[] = {1, 2, 3}; // aggregate init
[[maybe_unused]] int ar2[]{1, 2, 3};
}
135 changes: 135 additions & 0 deletions src/core/basics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Theory

## 1. Initialization in C++

C++ provides several ways to initialize objects. Each form has different semantics and use cases.

---

### 1.1 Default Initialization

Performed when an object is created **without any initializer**.

```cpp
T object;
new T;
```

- Built-in types: uninitialized
- Class types: default constructor is called

---

### 1.2 Value Initialization

Performed when an object is created with an **empty initializer**.

```cpp
T();
new T();
T object{};
T{};
new T{};
```

Also used in constructors:

```cpp
Class::Class() : member() {}
Class::Class() : member{} {}
```

- Built-in types: zero-initialized
- Class types: default constructor is called

---

### 1.3 Direct Initialization

Initializes an object using **explicit constructor arguments**.

```cpp
T object(arg);
T object(arg1, arg2);

T object{arg}; // since C++11
new T(args...);
static_cast<T>(other);
```

Used in constructors and lambdas:

```cpp
Class::Class() : member(args...) {}
[arg]() {};
```

---

### 1.4 Copy Initialization

Initializes an object **from another object or expression**.

```cpp
T object = other;
f(other);
return other;
throw object;
catch (T object);
```

Also used for arrays:

```cpp
T array[N] = { /* values */ };
```

---

### 1.5 List Initialization (since C++11)

Initializes objects using **brace-enclosed initializer lists**.

#### Direct List Initialization

```cpp
T object{arg1, arg2};
new T{arg1, arg2};

Class::Class() : member{arg1, arg2} {}
```

#### Copy List Initialization

```cpp
T object = {arg1, arg2};
return {arg1, arg2};
function({arg1, arg2});
```

#### Designated Initializers (since C++20)

```cpp
T object{ .des1 = arg1, .des2 = arg2 };
T object = { .des1 = arg1, .des2 = arg2 };
```

---

### 1.6 Aggregate Initialization

Initializes **aggregate types** (no user-defined constructors).

```cpp
T object = {arg1, arg2};
T object{arg1, arg2}; // since C++11
```

Designated initializers for aggregates (since C++20):

```cpp
T object = { .des1 = arg1, .des2 = arg2 };
T object{ .des1 = arg1, .des2 = arg2 };
```

- A specialized form of list-initialization
22 changes: 22 additions & 0 deletions src/core/datatypes/container/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Containers library
- The Containers library is a generic collection of class templates and algorithms that allow programmers to easilly implement common data structures.
- All container functions can be called concurrently by different threads on different containers
## 1. Sequence Containers
Sequence containers implement data structures which can be accessed sequentially.

|name|description|
|---|---|
|array|fixed-sized inplace contiguous array|
|vector|resizeable contiguous array|
|dequeue|double-ended queue|
|forward_list|singly-linked list|
|list|doubly-linked list|

## 2. Unordered Containers
Unordered associative containers implement unsorted (hashed) data structures that can be quickly searched (O(1) average, O(n) worst-case complexity).
|name|description|
|---|---|
|unordered_map|collection of key-value pairs, hashed by keys, keys are unique|
|unordered_set|collection of unique keys, hashed by keys|

TBD
81 changes: 81 additions & 0 deletions src/core/datatypes/container/sequence/Array.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// cppcheck-suppress-file [unreadVariable,unusedVariable]

/**
* std::array
*
* <array>
* template< class T, std::size_t N > struct array;
*/
#include <array> // for std::array
#include <iostream>

namespace {
void example() {
std::cout << "\n--- std::array Example ---\n";
// 1) Init
std::array<int, 3> m_array = {9, 100, 0};
// m_array = {1,2,3,5,6}; // ERROR

std::array<int, 3> a2{3, 4, 5};
std::array<int, 3> a3; // garbage values for a3[0]-> a4[]
std::array<int, 3> a4{}; // all elements have value 0
std::array<int, 3> a5{1}; // a5[0] = 0, others elements have value 0

// 2) Element access
std::cout << m_array.front() << std::endl;
std::cout << m_array.back() << std::endl;

int* ptr_arr = m_array.data();
std::cout << *(ptr_arr++) << " ";
std::cout << *(ptr_arr++) << " ";
std::cout << *(ptr_arr++) << " ";
std::cout << std::endl;

for (std::size_t i = 0; i < m_array.size(); ++i) {
std::cout << m_array.at(i) << " ";
}
std::cout << std::endl;

for (const int& e : m_array) {
std::cout << e << " ";
}
std::cout << std::endl;

// 3) Iterators
std::array<int, 3>::iterator it = m_array.begin();
std::array<int, 3>::iterator itEnd = m_array.end();
for (; it != itEnd; ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;

auto rIt = m_array.rbegin();
auto rItEnd = m_array.rend();
for (; rIt != rItEnd; rIt++) {
std::cout << *rIt << " ";
}
std::cout << std::endl;

// 4) Capacity
std::cout << m_array.max_size()
<< std::endl; // fixed-size => max_size = size
std::cout << m_array.size() << std::endl;
bool isEmpty = m_array.empty();

// 5) Operation
constexpr std::size_t xy = 4;
using Cell = std::array<unsigned char, 8>;
std::array<Cell, xy * xy> board;
board.fill({0xE2, 0x96, 0x84, 0xE2, 0x96, 0x80, 0,
0}); // "▄▀"; // fill means fill all 16 Cell with "▄▀"
// board = {Cell{0xE2, 0x96, 0x84, 0xE2, 0x96, 0x80, 0, 0},Cell{0xE2, 0x96, 0x84, 0xE2, 0x96, 0x80, 0, 0}};
for (std::size_t count{}; Cell c : board)
std::cout << c.data() << ((++count % xy) ? "" : "\n");
}
} // namespace

struct ArrayRunner {
ArrayRunner() { example(); }
};

static ArrayRunner autoRunner;
54 changes: 54 additions & 0 deletions src/core/datatypes/container/sequence/Vector.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// cppcheck-suppress-file [unreadVariable,unusedVariable,redundantInitialization]

// ArrayList
/**
* std::vector
*
* <vector>
*/
#include <iostream>
#include <vector> // for std::vector

namespace {
void example() {
std::cout << "\n--- std::vector Example ---\n";
// 1) Init
std::vector<int> m_vec = {9, 100, 0};
m_vec = {1, 2, 3, 5, 6}; // OK

std::vector<int> m_vec1{9, 100, 0};
std::vector<int> m_vec2;
std::vector<int> m_vec3{};
std::vector<int> m_vec4();

m_vec.assign({1, 1, 3});

// 2) Modifiers
m_vec.clear();

auto pos = m_vec.begin();
m_vec.insert(pos, 99);
pos = m_vec.begin(); // pos may be no longer valid, get a new one
m_vec.insert(pos, 9);
pos = m_vec.begin();
m_vec.erase(pos);

m_vec.push_back(1);
m_vec.push_back(2);
m_vec.push_back(3);
m_vec.push_back(4);

m_vec.pop_back();

for (const auto& e : m_vec) {
std::cout << e << " ";
}
std::cout << std::endl;
}
} // namespace

struct VectorRunner {
VectorRunner() { example(); }
};

static VectorRunner autoRunner;
Loading