Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.52/597: Рейтинг темы: голосов - 597, средняя оценка - 4.52
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2

С++ идиомы

31.07.2016, 19:20. Показов 149642. Ответов 34
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Перевод статей 1 и 2. Будет постепенно обновляться. Желающие внести вклад могут писать в ЛС.

 Комментарий модератора 
Тема открыта, просьба добавлять только посты с переводом, обсуждение здесь


Переведенные идиомы:
self-assignment in an assignment operator
Scope Guard
Shrink-to-fit
Checked delete
Pointer To Implementation
Получение адреса(ака взятие адреса aka Address-of)
nullptr
Iterator Pair
Coercion by Member Template
14
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
31.07.2016, 19:20
Ответы с готовыми решениями:

С++ идиомы - обсуждение
Тема создана для вопросов и обсуждений С++ идиом

Как и какие идиомы и паттерны можно (и лучше) применять?
Здравствуйте. Писал я проги для себя ну и так по мелочи, для абы кого, да и проги абы как, не задумываясь о том как какие идиомы (паттерны)...

Идиомы программирования
диома программирования — это некоторое часто применяемое действие в прораммировании. Это самый низкоуровневый шаблон проектировввния. ...

34
фрилансер
 Аватар для Алексей1153
6440 / 5634 / 1127
Регистрация: 11.10.2019
Сообщений: 14,978
14.03.2021, 21:21
Студворк — интернет-сервис помощи студентам
JeyCi,

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int main(int argc, const char *argv[])
{
    int a=2;
    {
       vector<unique_ptr<AbstractShape>>  v;
       v.emplace_back(new Square(a));
       v.emplace_back(new Circle(a));
       v.emplace_back(new Rectangle(a, 4));
            
        for(const auto& el : v)
        {
            cout << el->area() << '\n'; 
        }
    }
    return 0;
}
1
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
16.03.2021, 14:56
Цитата Сообщение от JeyCi Посмотреть сообщение
часто CRTP описывается только с template'ом и наследниками
Потому что именно это в его названии и заложено.

Вообще я убежден, что CRTP должен быть элементом дизайна, а не оптимизации.
Нет никакого смысла вводить его только ради оптимизации. Должны быть более фундаментальные причины.
1
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
16.03.2021, 15:44
JeyCi, я вам тут прикрепил pdf-ку со статьей из журнала C++ Report от 95 года по CRTP. Думаю полезно будет ознакомиться для полного понимания.
Вложения
Тип файла: pdf The-C-Report (CRTP).pdf (854.5 Кб, 27 просмотров)
2
Любитель чаепитий
 Аватар для GbaLog-
3745 / 1801 / 566
Регистрация: 24.08.2014
Сообщений: 6,020
Записей в блоге: 1
16.03.2021, 16:36
Цитата Сообщение от Алексей1153 Посмотреть сообщение
да, я слегка ошибся - у тебя запутанная архитектура ) Утечки не будет

Не по теме:

Кликните здесь для просмотра всего текста
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
anon@DESKTOP:/mnt/d/Projects/tmp$ valgrind --leak-check=full ./a.out
==75== Memcheck, a memory error detector
==75== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==75== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==75== Command: ./a.out
==75==
==75== error calling PR_SET_PTRACER, vgdb might block
4
12.56
8
==75==
==75== HEAP SUMMARY:
==75==     in use at exit: 56 bytes in 3 blocks
==75==   total heap usage: 11 allocs, 8 frees, 73,384 bytes allocated
==75==
==75== 16 bytes in 1 blocks are definitely lost in loss record 1 of 3
==75==    at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==75==    by 0x109189: main (crtp_leak.cpp:63)
==75==
==75== 16 bytes in 1 blocks are definitely lost in loss record 2 of 3
==75==    at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==75==    by 0x1091A7: main (crtp_leak.cpp:64)
==75==
==75== 24 bytes in 1 blocks are definitely lost in loss record 3 of 3
==75==    at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==75==    by 0x1091C5: main (crtp_leak.cpp:65)
==75==
==75== LEAK SUMMARY:
==75==    definitely lost: 56 bytes in 3 blocks
==75==    indirectly lost: 0 bytes in 0 blocks
==75==      possibly lost: 0 bytes in 0 blocks
==75==    still reachable: 0 bytes in 0 blocks
==75==         suppressed: 0 bytes in 0 blocks
==75==
==75== For counts of detected and suppressed errors, rerun with: -v
==75== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)

1
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
16.03.2021, 20:20
DrOffset, спасибо... начинаю понимать, как создаётся язык (что и есть цель ООП по сравнению с процедурным пр-ем), паттерны и Finite State Machine ... - прямо откровения от автора ... интересные... особенно понравилась фраза
baseFSM class provides a framework for programmer
я тогда посоветую ещё - Федор Г. Пикус | Идиомы и паттерны проектирования в современном С++ (2020) [PDF] - может здесь брала... стр 274-276 хорошо описаны ограничения CRTP классического и расширенного основным класслм (как описано в вашей pdf и как я пыталась кодом выше) -
Pros:
1) шаблон генерит функции для потомков авоматически, чтобы их не писать во всех потомках - в классическом варианте
2) по расширенной версии с базовым классом... использование перекрёстного приведения (своеобразный dynamic-cast)
Если во время выполнения выяснится, что фактический производный объект имеет тип, не являющийся комбинацией обоих базовых классов, то dynamic_cast завершится неудачно и вернёт NULL (или возбудит исключение, если мы используем не указатели, а ссылки)
- "обоих базовых классов" - это базового и template'ового... в вашей pdf в принципе, о том тоже указано...
вообще, интересный трюк - наследоваться от базового и от template'ового... - наверно, даже таким способом и страховку от "алмаза смерти" можно изобрести?... не пробовала ещё...
только вот получить наследника второй очереди - с этим наследуемым виртуальным clone(), задаваемым в шаблоне, чтобы не прописывать его во всех наследниках, - уже вроде не получится ....

Добавлено через 6 минут

P.S.
Кликните здесь для просмотра всего текста
Цитата Сообщение от GbaLog- Посмотреть сообщение
==75== 16 bytes in 1 blocks are definitely lost in loss record 1 of 3
==75== at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==75== by 0x109189: main (crtp_leak.cpp:63)
==75==
==75== 16 bytes in 1 blocks are definitely lost in loss record 2 of 3
==75== at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==75== by 0x1091A7: main (crtp_leak.cpp:64)
==75==
==75== 24 bytes in 1 blocks are definitely lost in loss record 3 of 3
==75== at 0x4C3217F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==75== by 0x1091C5: main (crtp_leak.cpp:65)

значит new от строк 63-65 надо потом delete.. т.е. они, вероятно, не от-move-ились в unique_ptr, а, наверно, от-copy-лись... простите за выражения
0
17.03.2021, 07:09

Не по теме:

Цитата Сообщение от JeyCi Посмотреть сообщение
т.е. они, вероятно, не от-move-ились в unique_ptr
а что и куда у вас должно "отмувнуться"? не вижу такого когда у вас.

0
17.03.2021, 07:31

Не по теме:


Цитата Сообщение от JeyCi Посмотреть сообщение
Shape(Shape&&) = default; // ? конструктор перемещения
//====
std::unique_ptr<AbstractShape> // родительский ptr в unique заворачивается...
вообще, действительно, как-то не прозрачно... но тема конструкторов, наверно, уже др. тема... или делать явный std::move ...
спасибо, что прогнали через Valgrind

0
17.03.2021, 07:31

Не по теме:

JeyCi, утечка там вот тут:

Code
1
2
3
4
5
std::unique_ptr<AbstractShape> clone() const override
{
     return std::make_unique<Derived> //создаётся НОВЫЙ объект обёртки
        (static_cast<Derived const&>(*this));//в конструктор передаётся КОПИЯ *this - снаружи this не удалится сам, так как создан new
}

0
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
18.03.2021, 08:57
Цитата Сообщение от DrOffset Посмотреть сообщение
CRTP должен быть элементом дизайна, а не оптимизации.
Нет никакого смысла вводить его только ради оптимизации. Должны быть более фундаментальные причины.
? вижу только одну возможную фундаментальную причину - не дублировать код в потомках (чтобы было легче сопровождать) и - вторую - не отдавать полиморфизм на откуп run-time'у (для скорости)... имхо
p.s.
для меня могут быть только 4 фундаментальные причины:
- для увеличения скорости,
- для минимизации памяти,
- для минимизации писанины,
- для того, чтобы не потерять что-нибудь (что приводит к memory leaks)...
разве есть ещё какие-то более фундаментальные причины, например для использования CRTP?..
0
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
18.03.2021, 09:16
Цитата Сообщение от JeyCi Посмотреть сообщение
для увеличения скорости,
Обычно там, где действительно нужен runtime-полиморфизм, никак не получится его заменить на compile-time.

Цитата Сообщение от JeyCi Посмотреть сообщение
разве есть ещё какие-то более фундаментальные причины
Я говорил только про выбор CRTP в качестве решения для замены runtime-полиморфизма.
И суть моих слов в том, что дизайн должен быть основным критерием, а не производительность. В смысле, что производительность - это следствие, а не первопричина.
0
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
18.03.2021, 13:07
Цитата Сообщение от DrOffset Посмотреть сообщение
CRTP должен быть элементом дизайна, а не оптимизации
ну в общем, да, - если по логике нужны будут разные реализации от одного интерфейса... то CRTP расширенный очень даже хорош (хоть некоторые и пеняют на "читаемость и отлаживаемость кода" по сравнению с использованием обычных Абстрактных классов )...
Единственная ситуация, когда вам действительно нужно использовать динамический полиморфизм, — это когда реализация недоступна во время компиляции; например, когда он загружен из динамической библиотеки.
- вот я пока останусь при такой точке зрения...
спасибо за view: performance <-design-> optimization (& 1<->3)
0
18.03.2021, 15:45

Не по теме:

Да хорош тему засерать и тролиху кормить.

0
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
23.03.2021, 18:40
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Зачем метод clone?
вот читаю книгу из #25 - так речь о CRTP-фабрике в главе 13 - там и примеры с clone()... а сам CRTP в главе 8 описывается... а wiki, наверно, вырвали кусок и этот clone() не заменили на любую более вразумительную функцию...
только сейчас поняла, почему clone() - рудимент от фабрики - может быть любая др. функция...
0
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
18.05.2021, 19:55
да, с CRTP-фабрикой, - примером с wiki, - я всё-таки поспешила...
Цитата Сообщение от DrOffset Посмотреть сообщение
CRTP должен быть элементом дизайна, а не оптимизации.
Нет никакого смысла вводить его только ради оптимизации. Должны быть более фундаментальные причины.
всё-таки смысл статического полиморфизма (в данном случае) - Lazy: CRTP...
That is possible because the method will be instantiated when called.
или здесь...
===
- полагаю, желание/потребность подрядить ленивые вычисления/методы и может стать фундаментальным аргументом в пользу выбора CRTP (иных пока не вижу)...
только я пока не выбирала ленивые методы... как бы не вижу в них преимуществ... разве что по памяти (чтобы функции-члены не инстанцировались в случае, если вдруг потом могут и не понадобится)... имхо

Добавлено через 4 минуты
p.s.
вероятно, для подмешивания этот трюк в основном используется... так же
MixIn функциональность не обязательно должна быть включена внутрь некоторого класса. Иногда возможно ее реализовать в виде свободной функции
0
262 / 151 / 33
Регистрация: 29.06.2019
Сообщений: 1,515
19.05.2021, 10:42
MixIn функциональность не обязательно должна быть включена внутрь некоторого класса. Иногда возможно ее реализовать в виде свободной функции
хотя, как справедливо подмечено, - просто ради удобства лучше инкапсулировать
With the CRTP, you can see that Sensitivity offers the interface of NumericalFunctions...
And with the template non-member functions you don’t. They would be hidden behind a #include somewhere.
===
Цитата Сообщение от JeyCi Посмотреть сообщение
для подмешивания
оставлю работающий код (с линка - просто там нарезки) для ситуации подмешивания нескольких Базовых классов
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
// https://habr.com/ru/post/210894/
 
// Возможно, вы заметили в предыдущих главах “Явный интерфейс” и “MixIn наоборот” я использовал открытые функции в производном классе. Вообще говоря, это не очень хорошо, так как нарушает инкапсуляцию. Получается, что наружу у нас “торчат” функции, которые не предназначены для того, что пользователь вызывал их напрямую. 
//Можно решить эту проблему, сделав базовые классы друзьями производного. После этого можно вносить эти функции в private секцию, но представьте, что вам нужно отнаследовать от нескольких базовых MixIn’ов. Придется делать друзьями все базовые классы. Для комплексного решения этой проблемы, а также для того, чтобы обеспечить компиляцию на некоторых старых компиляторах, можно ввести новый уровень косвенности. Он представляет из себя структуру, функции которой перенаправляют вызовы из базы в производный класс.
 
#include <iostream>
 
using namespace std;
 
//  можно ввести новый уровень косвенности. Он представляет из себя структуру, функции которой перенаправляют вызовы из базы в производный класс.
// indirection level
struct access
{
    template<typename Impl>
    static void on_handle_connect(Impl* impl) {impl->handle_connect();}
 
    template<typename Impl>
    static void on_handle_response(Impl* impl) {impl->handle_response();}
};
 
// Теперь из базовых классов, мы вызываем не функции производного, а функции промежуточной структуры.
// BASE
template<typename D>
struct connection_handler
{
    // ...
    void on_connection()
    {
        access::on_handle_connect(static_cast<D*>(this));
    }
};
 
template<typename D>
struct response_handler
{
    // ...
    void on_response()
    {
        access::on_handle_response(static_cast<D*>(this));
    }
};
 
// В производном же классе нам достаточно внести в друзья только структуру access.
// DERIVED
class combined_handler : public connection_handler<combined_handler>, 
public response_handler<combined_handler>
{
    private:
        friend struct access;
        void handle_connect(){ std::cout << "handle_connect: " << __PRETTY_FUNCTION__ << std::endl; }
        void handle_response(){ std::cout << "handle_response: " << __PRETTY_FUNCTION__ << std::endl; }
};
 
 
int main()
{
    combined_handler s1;
 
    s1.on_connection();
    s1.on_response();
   
}
/*
handle_connect: void combined_handler::handle_connect()
handle_response: void combined_handler::handle_response()
*/

- всё-таки доп. уровень косвенности в CRTP через друзей может помочь и избежать "Алмаза смерти" (подробнее здесь - смысл friend в подмешивании)...
===
и так же (по последнему линку) - это попытка избавиться от большого количества static_cast'ов при реализации CRTP-паттерна, которая как раз и заключается в выносе всех static_cast'ов на верх. уровень иерархии, а чтобы оттуда не получить ромбовидного наследования - использование template'а, принимающего параметром тоже template (а не конкретный type)
Note that the template parameter is not just a typename, but rather a template<typename> class. This simply means that the parameter is not just a type, bu rather a template itself, templated over a type whose name is omitted. For example crtpType can be
===
в общем, CRTP, конечно, вариант, когда все типы известны на этапе компиляции, - для статического полиморфизма... но всё-таки глубокие иерархии всё равно не стоит делать... а диспетчеризация через visit и variant в std даёт нужное и без иерархий... появление std::variant -- всё-таки большой шаг вперёд был в std... имхо
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
19.05.2021, 10:42
Помогаю со студенческими работами здесь

Английские идиомы: как правильно перевести in its own right?
Как правильно перевести in its own right? Например, вот в таком контексте: Добавлено через 3 минуты В русском переводе книги...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
35
Ответ Создать тему
Новые блоги и статьи
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
Расскажи мне о Мире, бродяга
kumehtar 12.11.2025
— Расскажи мне о Мире, бродяга, Ты же видел моря и метели. Как сменялись короны и стяги, Как эпохи стрелою летели. - Этот мир — это крылья и горы, Снег и пламя, любовь и тревоги, И бескрайние. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru