-
Notifications
You must be signed in to change notification settings - Fork 4
Module4 STL #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Module4 STL #24
Conversation
eupp
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked approx. half of the prepared tasks. I will have a look at the remaining tasks later.
Overall good job, the text of the theory materials improved significantly compared to the module 3!
StandardLibraryEssentials/StandardTemplateLibrary/lesson-info.yaml
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/lesson-info.yaml
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/setContainers/test/test.cpp
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/mapContainers/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/mapContainers/src/task.cpp
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/mapContainers/test/test.cpp
Outdated
Show resolved
Hide resolved
|
A few thoughts:
|
Previous notes taken into account
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLOverview/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLAlgorithms/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLAlgorithms/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/STLAlgorithms/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/InputOutputStreams/task.md
Outdated
Show resolved
Hide resolved
StandardLibraryEssentials/StandardTemplateLibrary/InputOutputStreams/task.md
Outdated
Show resolved
Hide resolved
|
Last task of Templates module may be a bit controversial in terms of covered information, since I’ve included a brief explanation of type traits and variadic templates to it. I haven’t came up with anything else that could be presented in this lesson, other than basic template specialization idea. I don't mind deleting this part, but I thought it may be a nice sneak peek to metaprogramming and other high-level stuff. |
Task descriptions and tests in progress.
This reverts commit 32c2aea.
| @@ -0,0 +1,9 @@ | |||
| In this part of the course, you will learn about such a feature of the C++ language as templates. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| In this part of the course, you will learn about such a feature of the C++ language as templates. | |
| In this part of the course, you will learn about the templates in the C++ language. |
| In essence, templates are a means to write generic code that can work with varying types. They allow you to write a single function or class that can adapt to different types, without the need to write separate functions or classes for each type. | ||
|
|
||
| The following topics will be covered: | ||
| * Definition of templates for functions and classes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| * Definition of templates for functions and classes | |
| * Template functions and classes |
| * Definition of templates for functions and classes | ||
| * Type-inference, `auto` and `decltype` keywords, template argument deduction | ||
| * Type aliases: `using` and `typedef` | ||
| * Template specialization |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Type inference:
autoanddecltype - Template argument deduction
- Type aliases:
usingandtypedef - Template specialization
| @@ -0,0 +1,75 @@ | |||
| Imagine that you have a function for calculating the sum of two numbers. If you want to calculate the sum of two integers, you can write a function that takes two `int` numbers as arguments and returns their sum. However, suppose you also want to have such a function for `double`, `long long`, `float`, and a custom type such as `Fraction`. You will have to write a separate function for each type. This becomes inconvenient, as you end up writing multiple functions that essentially do the same thing but with different data types. | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Imagine that you have a function for calculating the sum of two numbers. If you want to calculate the sum of two integers, you can write a function that takes two `int` numbers as arguments and returns their sum. However, suppose you also want to have such a function for `double`, `long long`, `float`, and a custom type such as `Fraction`. You will have to write a separate function for each type. This becomes inconvenient, as you end up writing multiple functions that essentially do the same thing but with different data types. | |
| Imagine that you have a function for calculating the sum of two numbers. If you want to calculate the sum of two integers, you can write a function that takes two `int` numbers as arguments and returns their sum. However, suppose you also want to have such a function for `double`, `long long`, `float`, or some custom data type. You will have to write a separate function for each type. This becomes inconvenient, as you end up writing multiple functions that essentially do the same thing but with different data types. |
|
|
||
| Templates are designed to address this exact issue. They allow you to write a single function that can work with different types. For instance, you can write a template function that takes two arguments of any type and returns their sum as a variable of the same type. | ||
|
|
||
| The syntax for creating a template function is simple: you start with the `template` keyword, followed by the `typename` keyword, and then include the type name you want to use as a template parameter. Then, you can use this type name in the function as if it were a regular type: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| The syntax for creating a template function is simple: you start with the `template` keyword, followed by the `typename` keyword, and then include the type name you want to use as a template parameter. Then, you can use this type name in the function as if it were a regular type: | |
| The syntax for creating a template function is simple: you start with the `template` keyword, followed by the `typename` keyword, and then include the type name you want to use as a template parameter. Then, you can use this type name in the function as if it was a regular type: |
| When the compiler encounters any call to a template function, it first checks for a specialized version of the function for the argument's type. If such a version exists, it will employ it; otherwise, it will use the general version. | ||
| There is a technique called metaprogramming, which allows you to write code that generates other code using templates and template specialization. Since it is a complex topic, we will not cover it in this course, but you can find more information about it in the [C++ documentation](https://en.cppreference.com/w/cpp/meta). However, there is a feature called "type traits" that can be helpful in some cases. Type traits are a set of classes that provide information about types at compile time. You can use them to check if a type has a specific property, like being a pointer or reference. You can find more information about type traits in the [C++ documentation](https://en.cppreference.com/w/cpp/header/type_traits). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's not mention "type traits". It is a complicated feature, which can only confuse novice programmers. This feature deserves its own series of tasks and should be properly explained.
| There is a technique called metaprogramming, which allows you to write code that generates other code using templates and template specialization. Since it is a complex topic, we will not cover it in this course, but you can find more information about it in the [C++ documentation](https://en.cppreference.com/w/cpp/meta). However, there is a feature called "type traits" that can be helpful in some cases. Type traits are a set of classes that provide information about types at compile time. You can use them to check if a type has a specific property, like being a pointer or reference. You can find more information about type traits in the [C++ documentation](https://en.cppreference.com/w/cpp/header/type_traits). | ||
| Since each specialization requires a separate implementation, it may not always be the best solution. In many cases, you can try to find any common type property and use it's checker, like the `std::is_pointer` function to check if the type is a pointer and handle it within the general function. This way, you can avoid code duplication and make the code more readable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove this paragraph and example too.
| * `erase(value)` - removes the element `value` from the container | ||
| * `find(value)` - returns an iterator to the element `value` if it is found, otherwise, it returns `end()` | ||
|
|
||
| To be fair, all these methods have **amortized** `O(1)` complexity, since sometimes hashes of different keys can be the same. This is called a [collision](https://en.wikipedia.org/wiki/Hash_table#Collision_resolution). In such situations, the whole table needs to be rehashed, which is the reason why the methods of an unordered container can perform in `O(n)` time in the worst-case scenario. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Move this paragraph after the next two paragraphs (about hash table and std::hash), and put it under a hint.
| } | ||
| ``` | ||
|
|
||
| You need to implement a [cache](https://en.wikipedia.org/wiki/Cache_(computing)) system with an [LRU](https://en.wikipedia.org/wiki/Cache_replacement_policies#Least_recently_used_(LRU)) (Least Recently Used) policy. Its member functions are defined in the `/include/Cache.h` file. Since cache is a very fast type of storage, you will need to use hashing to implement it. The provided solution uses `std::list` and `std::unordered_map`, but you can choose any container from the STL for your own implementation. At first, define a structure inside `/include/Cache.h` file that will store key-value pairs. Then, define another structure that will store the key and an iterator to the corresponding element in the list. After defining these structures, you can implement the cache operations on `task.cpp`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The provided solution uses
std::listandstd::unordered_map, but you can choose any container from the STL for your own implementation.
Maybe let's remove this suggestion? I think it can only confuse the students.
Using just std::list and std::unordered_map is fine for this task.
| In addition to all that we have learned so far, the STL also provides a number of algorithms that can be used on a range of elements. These algorithms are implemented as functions that usually utilize iterators. In this task, we will look at some of the most commonly used algorithms. There are many more algorithms available in the STL, and you can find a complete list [here](https://en.cppreference.com/w/cpp/algorithm). | ||
| We highly encourage you to explore the STL algorithms by yourself and try to use them in your code! They are useful and can save you a lot of time and effort. | ||
|
|
||
| #### 1. `std::sort()` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is still relevant (there is still no mentioned of iterators categories expected by the algorithms).
|
|
||
| # Running learner side code | ||
| # Use PROJECT_NAME dependent names of targets for the plugin support to work correctly. | ||
| add_executable(lesson-run ${SRC}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a problem with this.
First, "lesson-run" name is not unique (it is easy to give the same name to another task by mistake).
Second, as the comment above mentions, for plugin integration to work properly, the name has to be dependent on the $PROJECT_NAME variable.
So I suggest to revert it back to ${PROJECT_NAME}-run and instead change the name of the project. So replace:
project(StandardLibraryEssentials-StandardTemplateLibrary-SequentialContainerAdaptors)
to just
project(StandardLibraryEssentials-SequentialContainerAdaptors)
or even:
project(SequentialContainerAdaptors)
Same applies to lesson-test target.
Two tasks done, 8 in WIP state, will be ready soon.