- Notifications
You must be signed in to change notification settings - Fork 17
[DRAFT] C++ chapter 14.2 #301
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
base: main
Are you sure you want to change the base?
Conversation
a7f32b7 to 0bbef64 Compare cpp/cpp_chapter_0142/text.md Outdated
| w | ||
| ``` | ||
| | ||
| Символьный тип `char` является целочисленным, поэтому может выступать в качестве базового для перечисления. В этом примере мы вызвали появившуюся в C++23 функцию [std::to_underlying()](https://en.cppreference.com/w/cpp/utility/to_underlying.html). Она приводит значение перечисления к базовому типу. До C++23 с той же целью приходилось выполнять явное приведение типов через `static_cast`: |
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.
Надо бы пояснить зачем нужен std::to_underlying(), в чем его преимущество над кастом. Например для использования в обобщенном коде:
import std; enum ServerState { down, starting, ready, stopping }; enum HttpPort : std::uint16_t { def = 80, tls = 443 }; template <class T> void pint_enum_value(std::string name, T value) { std::println("{}: {}", name, std::to_underlying(value)); } int main() { pint_enum_value("down", ServerState::down); pint_enum_value("ready", ServerState::ready); pint_enum_value("tls", HttpPort::tls); }Также, если кто-то изменит базовы тип на больший, то не будет опасного сужающего преобразования.
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.
Готово
cpp/cpp_chapter_0142/text.md Outdated
| | ||
| int main() | ||
| { | ||
| const char level = std::to_underlying(LogLevel::Info); |
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.
В этой строчке явно указан результирующий тип, что несколько понижает ценность задачи. Кроме того человека невнимательного (вроде меня) может сбить с толку, что изначально работаем со значением перечисления. Если не быть внимательным, то ожидаешь вывод конкретного значение. А sizeof замыливается.
Предлагаю сначала рассказать о std::underlying_type_t и в примере использовать его:
import std; enum class LogLevel : char { Trace, Debug, Info, Warn, Error }; int main() { std::println("{}", sizeof(std::underlying_type_t<LogLevel>)); }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.
Заменила задачу на другую.
cpp/cpp_chapter_0142/text.md Outdated
| true | ||
| ``` | ||
| | ||
| Реализуйте функцию `sum_if()`, которая принимает два параметра. Перый — это словарь `std::map` с ключами - строками и значениями типа `std::size_t`. Второй параметр - функция-предикат, принимающая строку и возвращающая `bool`. Функция `sum_if()` должна вернуть сумму значений элементов словаря, для ключей которых предикат возвращает `true`. {.task_text} |
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 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.
Переформулировала условие. Хочется, чтобы пользователь по описанию сам осилил составить типы параметров.
| | ||
| return res; | ||
| } | ||
| ``` |
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.
ИМХО, после задачи стоит добавить, что тоже самое можно сделать с помощью стандартных алгоритмов. Например: c помощью std::accumulate():
import std; using dict_t = std::map<std::string, std::size_t>; std::size_t add_if(std::size_t sum, dict_t::value_type item) { return item.first.empty() ? sum : sum + item.second; } int main() { dict_t dict {{"01", 100}, {"03", 20}, {"", 1000}, {"05", 5}, {"", 2200}, {"", 1}, {"10",3}}; const std::size_t sum = std::accumulate(dict.begin(), dict.end(), 0, add_if); std::println("sum: {}", sum); }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.
Скорректировала условие задачи. Добавила про accumulate() в него.
cpp/cpp_chapter_0142/text.md Outdated
| | ||
| Классы — это более сложные абстракции, чем фундаментальные типы: | ||
| - Фундаментальные типы максимально близки к аппаратному представлению чисел. Переменная фундаментального типа — это всего лишь небольшая область памяти, которую компилятор трактует определенным образом. Большинство операций над фундаментальными типами сводится к единственной машинной команде. | ||
| - Классы же имеют конструктор и деструктор. Их поля могут находиться в разных участках памяти. Для чтения и записи полей могут быть реализованы методы произвольной сложности. |
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.
Их поля могут находиться в разных участках памяти.
Это некорректное утверждение. Все поля экземпляра класса располагаются в единой области памяти. Другое дело, что поля могут указывать на другие области динамической памяти, и управление этой памятью скрыто за фасадом класса.
Нужно переформулировать это предложение и возможно стоит пояснить на примере. Можно взять std::vector<> и рассказать, что поля вектора лежат в одном фрагменте памяти, а массив элементов в другом.
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.
Переформулировала эту часть.
cpp/cpp_chapter_0142/text.md Outdated
| public: | ||
| explicit File(std::vector<Section> sections); | ||
| std::size_t sections_count(); | ||
| std::pair<Section, std::size_t> findSection(std::function<bool(Section s, std::size_t idx)>); |
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.
Наверное, лучше так:
std::pair<Section, std::size_t> findSection(std::function<bool(Section, std::size_t)> pred);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.
Done
cpp/cpp_chapter_0142/text.md Outdated
| | ||
| Перед вами класс `File`, хранящий секции файла некоего формата. {.task_text} | ||
| | ||
| Добавьте в объявление класса метод `findSection()`. Он принимает объект `std::function` с аргументом шаблона — типом функции-предиката. Она в свою очередь принимает два параметра: секцию `Section` и индекс секции `std::size_t`. Функция `findSection()` возвращает пару: первую секцию файла\, для которой предикат вернул `true`, и ее индекс. Если такой секции нет, функция возвращает пустую секцию и индекс, равный `std::numeric_limits<std::size_t>::max()`. {.task_text} |
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.
ИМХО, скомкано и сложно для понимания. Проще взглянуть на определение функции и так понять, что нужно сделать. Предлагаю сначала сказать про входной параметер и выходное значение, а потом в отдельных предложения описать их. Также можно ввести дополнительные типы и ссылаться на них:
struct Section { std::string header; std::string name; std::string contents; }; using FindPred = bool(Section, std::size_t); using FindRes = std::pair<Section, std::size_t>; ...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.
Переформулировала
cpp/cpp_chapter_0142/text.md Outdated
| Так выглядит инициализация единицами массива из тысячи элементов: | ||
| | ||
| ```cpp | ||
| int offsets[1000] = {1}; |
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.
Это неверно:
import std; int main() { // будет заполнен только 1-ый элемент int arr1[4] = {1}; std::println("arr1: {}", arr1); // будут заполнены все элементы int arr2[4] = {}; std::fill(std::begin(arr2), std::end(arr2), 2); std::println("arr2: {}", arr2); }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.
Да, опечаталась. В предыдущем предложении же именно это и говорилось. Добавила задачу.
| float samples[3] = {4.5, 2.0, -1.1}; | ||
| ``` | ||
| | ||
| Если длина списка инициализации меньше длины массива, оставшиеся элементы заполняются нулями (даже если 0 не является корректным значением для типа). |
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.
Предлагаю также пояснить как заполнять массив деволтными значениями:
int arr[16] = {}; int arr[16] {};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 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 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.
С твоим комментом выше она получилась чуть более подробной.
No description provided.