Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.15.27.232] |
|
Страницы: (32) « Первая ... 23 24 [25] 26 27 ... 31 32 ( Перейти к последнему сообщению ) |
Сообщ.
#361
,
|
|
|
Цитата D_KEY @ Да, я тоже что-то такое помню, но также помню, что там был некий вырожденный случай, когда весь код в одном файле и компилятору дрступен весь код сразу. Но если вынести код с std::function в другие единицы трансляции, то аллокации в принципе неизбежны. Я помню был какой-то похожий спор с твоим участием (кажется в тематике), где в итоге обнаружилось, что std::function не уступает Dшным замыканиям |
Сообщ.
#362
,
|
|
|
Цитата applegame @ Но если вынести код с std::function в другие единицы трансляции, то аллокации в принципе неизбежны. А lto не помогает в таких случаях разве? |
Сообщ.
#363
,
|
|
|
Оно?
https://en.cppreference.com/w/cpp/experimental/scope_exit https://en.cppreference.com/w/cpp/experimental/scope_fail https://en.cppreference.com/w/cpp/experimental/scope_success Хотя как по мне - еще один синтаксический сахар, и не более. можно заменить тем же std::unique_ptr с кастомным делитером. |
Сообщ.
#364
,
|
|
|
Костыли далеко не всегда являются реальной проблемой. Но это все равно костыли. Например, std::enable_if - это жутчайший и уродский костыль, но наверняка Qraizer так не считает. Да и реальной проблемой он не является
Добавлено Цитата D_KEY @ lto умеет менять код сгенеренный компилятором? А lto не помогает в таких случаях разве? |
Сообщ.
#365
,
|
|
|
Цитата applegame @ Костыли далеко не всегда являются реальной проблемой. Про костыли я тебе выше написал. Это не костыль. Вернее, если это костыль, то и в D - тоже костыль. Цитата Например, std::enable_if - это жутчайший и уродский костыль Вот тут согласен. Ну, кстати, if constexpr почти все решает |
Сообщ.
#366
,
|
|
|
Цитата applegame @ Я его не использую. Не нужно было просто. Но это и не костыль, это составная часть интерфейса std в части поддержки парадигмы метапограммирования, которая помимо этого средства включает в себя ещё и большое количество других. На основе этой парадигмы ты можешь учить компилятор работать с любыми сущностями на основе их свойств и характеристик, а не только пользоваться предопределёнными и стандартизированными наборами для ограниченного числа сущностей и определёнными в Стандарте. Или ты шейдеры для GPU тоже называешь костылями, тогда как истинно правильными и единственно правоверными считаешь mutlitexturing, еnvironment lighting, mipmapping, T&L и ещё с десяток предопределений? Например, std::enable_if - это жутчайший и уродский костыль, но наверняка Qraizer так не считает. Добавлено Цитата D_KEY @ Костыль, костыль. И то, и это тоже. Негоже управлять ресурсами вручную. Негоже строить безотказность кода на условных конструкциях, не имеющих отношения к инвариантам. За которые и непонятно кто ещё отвечает. И то, и другое, и третье имеет место в scope, как и где его не реализуй. Вернее, если это костыль, то и в D - тоже костыль. |
Сообщ.
#367
,
|
|
|
использовать scope(exit) в качестве иммитации RAII действительно глупо. Но бывают случаи где сия конструкция вполне уместна.
Например, я писал обертку для постгресовской родной либы libpq. Она написана на сяшке (как и весь постгрескуль). Там память захватывается самой либой, а освобождается уже клинтским кодом путем вызова соответствующей функции. Это освобождение в моей обертке фигурировало буквально внутри одной функции. Я использовал там scope(exit) так как посчитал абсолютно бесполезным городить отдельный класс вместо одной сраной строчки: scope(exit) PQfree(res). Кроме того scope(exit) можно применять не только для освобождения ресурсов. Я пихал в него временный отладочный код вроде изменения счетчиков и всяких логов. |
Сообщ.
#368
,
|
|
|
Цитата applegame @ Она написана на сяшке (как и весь постгрескуль). Там память захватывается самой либой, а освобождается уже клинтским кодом путем вызова соответствующей функции. Это освобождение в моей обертке фигурировало буквально внутри одной функции. Я использовал там scope(exit) так как посчитал абсолютно бесполезным городить отдельный класс вместо одной сраной строчки: scope(exit) PQfree(res). Ты просто видимо из за отсутствия возможностей в D неверно спроектировал работу с библиотекой с точки зрения С++. Поэтому тебе и проще было сделать так. В С++ такой подход - это не проще, это будет тупо костыль. Вот про эту либу ты говоришь? https://postgrespro.ru/docs/postgresql/9.6/libpq-connect Во первых тут нет никакой функции PQfree. Есть: Цитата PQfinish Закрывает соединение с сервером. Также освобождает память, используемую объектом PGconn. void PQfinish(PGconn *conn); Во вторых - судя по документации, туда как раз RAII класс и просится, не хочешь городить класс, пиши auto dbCon = std::unique_ptr<PGconn>(PQconnectdb(psql_connect_info), [](PGconn* pCon){PQFree(pCon)}) и все, больше не нужно задумываться ни о чем. Так что ИМХО, пример так себе. Вот в своей либе, ты передаешь в PQFree(res) - а откуда ты его - res - получил? Вызвал коннект? Так значит уже не ради одной строчки класс городить, а ради двух получается? Или как? Цитата applegame @ Кроме того scope(exit) можно применять не только для освобождения ресурсов. Я пихал в него временный отладочный код вроде изменения счетчиков и всяких логов. Это очень просто делается классом-оберткой. В D возможно эта функция полезна, там же вроде GC? А в С++ она просто нахер никому не нужна. Ну не нужна она, если нужно что то подобное - это делается 1 раз за 2 минуты на коленке, и используется везде где нужно. Это как знаешь, сказать в C#/Java есть ах**наая плюшка finally, а в С++ ее нет, бе бе бе. Вы мудохайтесь там теперь и живите с этим, а я finally юзаю и доволен. Ну как то вот так это выглядит Ну и к слову, встречал что если класс в D создавать через new, то порядок вызовов с этим scope(exit) - уже не такой однозначный, а все из за GC, так что даже эта "плюшка" может запросто поломать программу. Ей очень осторожно нужно пользоваться. А значит уже и ценность ее, какую ты в нее вкладываешь, сомнительная. Вот собственно тут об этой особенности и пишут: https://forum.dlang.org/thread/kjkdfcnpgdeg...forum.dlang.org Т.е. как минимум один уже выхватил сигфолт в своей программе из за этого scope(exit) |
Сообщ.
#369
,
|
|
|
Цитата Wound @ Нет, ты ошибаешься. В D можно написать также как и в C++, используя вместо классов структуры, без использования GC и с точно таким же автоматическим вызовом дуструктора при выходе из скоупа.Ты просто видимо из за отсутствия возможностей в D неверно спроектировал работу с библиотекой с точки зрения С++. Поэтому тебе и проще было сделать так. Цитата Wound @ Да, давно писал, подзабыл, правильно PQClear.Во первых тут нет никакой функции PQfree. Цитата Wound @ Нет, PQFinish я как раз вызываю в деструкторе класса Connection. А эти коннекшены я держу в пуле, все по взрослому, тут RAII не нужно, как и scope(exit) или unique_ptr.Во вторых - судя по документации, туда как раз RAII класс и просится, не хочешь городить класс, пиши auto Цитата и все, больше не нужно задумываться ни о чем. Так что ИМХО, пример так себе. Вот в своей либе, ты передаешь в PQFree(res) - а откуда ты его - res - получил? Вызвал коннект? Так значит уже не ради одной строчки класс городить, а ради двух получается? Или как?dbCon = std::unique_ptr<PGconn>(PQconnectdb(psql_connect_info), [](PGconn* pCon){PQFree(pCon)}) Ну а вообще, когда я был молодым и глупым и сильно фанател по плюсам, вот это вот: Цитата Wound @ auto dbCon = std::unique_ptr<PGconn>(PQconnectdb(psql_connect_info), [](PGconn* pCon){PQFree(pCon)}) Мне казалось класной штукой. Но как только я увидел и попробовал D, Ruby, Haskell, Erlang, Elixir, Python, и прочее, я осознал, что это просто нечитаемое говно. Да ты сам, помню, ругал плюсы за уродливое метапрограммирование. Сравни: auto res = PQExec(...); scope(exit) PQClear(res); Чисто и любому, деже не умеющему в D, ясно что происходит. Можно конечно написать RAII обертку, но я давно переболел ООП головного мозга и перестал писать классы/структуры на малейший чих. Цитата Wound @ Не понимаю о чем ты. Что именно ты слышал? Ну и к слову, встречал что если класс в D создавать через new, то порядок вызовов с этим scope(exit) - уже не такой однозначный, а все из за GC, так что даже эта "плюшка" может запросто поломать программу. Ей очень осторожно нужно пользоваться. А значит уже и ценность ее, какую ты в нее вкладываешь, сомнительная. |
Сообщ.
#370
,
|
|
|
Цитата applegame @ Нет, ты ошибаешься. В D можно написать также как и в C++ используя не классы, а структуры, без использования GC и с точно таким же автоматическим вызовом дуструктора при выходе из скоупа. Ну не удивительно, я же не пишу на D, поэтому я предположил. А раз есть такая возможность - значит, выходит просто ты так спроектировал, что тебе проще вызвать scope(exit), вместо нормальной, красивой, надежной RAII обертки. Цитата applegame @ Нет, PQFinish я как раз вызываю в деструкторе класса Connection. А эти коннекшены я держу в пуле, все по взрослому, тут RAII не нужно, как и scope(exit) или unique_ptr. Ну так я же не знаю что ты там использовал, PQfree я не нашел, а под твое описание подпадает только PQFinish. PQClear же работает в связке с PQExec, опять же это все можно обернуть в обертку. Как сделано у тебя, правильно не правильно, не суть важно. Важно то, что тот контекст в котором ты говоришь, что якобы удобно писать scope(exit) вот тут - это удобно при твоей архитектуре приложения и удобно в том языке, в котором ты пишешь. Т.е. это не фича, что без нее вот тут будет плохо, это просто ты так написал свою программу. Я например напишу так, что в scope(exit) не будет никакого смысла, другой напишет так, что без goto не обойдешься. Цитата applegame @ Ну а вообще, когда я был молодым и глупым и сильно фанател по плюсам, вот это вот: Цитата Wound @ Сегодня, 13:31 auto dbCon = std::unique_ptr<PGconn>(PQconnectdb(psql_connect_info), [](PGconn* pCon){PQFree(pCon)}) Мне казалось класной штукой. Но как только я увидел и попробовал D, Ruby, Haskell, Erlang, Elixir, Python, и прочее, я осознал, что это просто нечитаемое говно. Да ты сам, помню, ругал плюсы за уродливое метапрограммирование. Таки да, я же не спорю что в С++ вырвиглазные шаблоны, в которых без поллитрyхи не разберешься. Я с этим полностью согласен. Но речь то шла не о вырвиглазных шаблонах. Цитата applegame @ Сравни: CollapsedWrap disabledLine numbers off auto res = PQExec(...); scope(exit) PQClear(res); Чисто и любому, деже не умеющему в D, ясно что происходит. Можно конечно написать RAII структурку, но я давно переболел ООП головного мозга и перестал писать классы/структуры на малейший чих. Вся фишка в том, что возможно это чисто и ясно в D, но в С++ такие махинации чреваты багами, поэтому в С++ приходится писать в RAII стиле не потому что это как то круто, модно, молодежно, а потому чтоб сократить число потенциальных багов. Да и удобнее банально этим будет пользоваться, чем голыми указателями и Си функциями. Это источник многих ошибок, вот чтоб этого избежать и пишут RAII обертки, тем более что язык это поддерживает искаропки. Так почему бы и не воспользоваться этим преимуществом. Добавлено Цитата applegame @ Не понимаю о чем ты. Что именно ты слышал? Я же ссылку привел выше, ок продублирую еще раз: https://forum.dlang.org/thread/kjkdfcnpgdeg...forum.dlang.org Вот тут чувак выхватил сигфолт благодаря GC и scope(exit). Добавлено Я вот допустим писал какую то хрень, связанную с вычиткой ACL в винде и ее последующим парсингом, жуткая хрень, пятиэтажные вложенные структуры, везде одни сплошные указатели, все освобождается какими то специфическими функциями, куча всякой дряни. Мне реально было проще взять все эти указатели и обернуть в unique_ptr с кастомным делитером, и вообще не нужно парится по поводу утечек, при любых раскладах. в итоге мне вообще фиолетово было на какие то там ошибки, которые могут произойти(нет они фиксировались и в логе и юзеру), просто сам ресурс - уже полностью контролируется компилятором, т.е. утечки будут только если в компиляторе баг. А это надежнее, чем писать во многих разных местах руками освобождение ресурса, потому как ты можешь не то освободить, забыть написать, не там освободить. Ручное управление ресурсом - всегда хуже автоматического, потому как является источником многих косяков и багов. |
Сообщ.
#371
,
|
|
|
Цитата applegame @ Чё-то я в этом списке Delphi не вижу. Непорядок? Но как только я увидел и попробовал D, Ruby, Haskell, Erlang, Elixir, Python, и прочее, я осознал, что это просто нечитаемое говно. Добавлено Цитата applegame @ Это прекрасно, пока не встретишьauto res = PQExec(...); scope(exit) PQClear(res); Чисто и любому, деже не умеющему в D, ясно что происходит. Можно конечно написать RAII обертку, но я давно переболел ООП головного мозга и перестал писать классы/структуры на малейший чих. auto res1 = PQExec(...); scope(exit) PQClear(res1); auto res2 = PQExec(...); scope(exit) PQClear(res1); auto res3 = PQExec(...); scope(exit) PQClear(res1); |
Сообщ.
#372
,
|
|
|
Цитата applegame @ Мне казалось класной штукой. Но как только я увидел и попробовал D, Ruby, Haskell, Erlang, Elixir, Python, и прочее, я осознал, что это просто нечитаемое говно. Я тоже пробовал много чего, в том числе и то, что указал ты (кроме elixir, да и D мало слишком). Я не считаю C++ лучшим или что-то такое, но вот RAII очень крутая (и при этом простая) концепция. Как раз всякие менеджеры контекста в питоне, которые я активно использую, таки костыли. Но это уже лучше всяких finally и defer/scope(exit). Добавлено Цитата applegame @ Сравни: auto res = PQExec(...); scope(exit) PQClear(res); Чисто и любому, деже не умеющему в D, ясно что происходит. Ага, это пока в очередной раз фигача подобный код ты не забудешь воткнуть свой scope(exit). Нафиг. Владелец пишется один раз (благодаря умным указателям это иногда просто typedef/using), используется потом много где просто как: auto res = PQExec(...); Сравнивай. Добавлено Цитата applegame @ Можно конечно написать RAII обертку, но я давно переболел ООП головного мозга и перестал писать классы/структуры на малейший чих. ООП не имеет никакого отношения к теме. Совсем. Я бы даже сказал, что без GC нормального ООП быть не может, но чистые плюсовики меня растерзают, поэтому я не стану этого говорить Обертку во многих случаях даже писать не придется - есть unique_ptr и shared_ptr. Напишешь один using и вперед. |
Сообщ.
#373
,
|
|
|
Цитата D_KEY @ Терзать не буду, но вот путаницу с ООП и ОП отмечу.Я бы даже сказал, что без GC нормального ООП быть не может, но чистые плюсовики меня растерзают, поэтому я не стану этого говорить Цитата D_KEY @ И я вот не понимаю, в чём сложность зафиксировать контракты для компилятора, а не полагаться на бессбойность своих шаловливых рук:Обертку во многих случаях даже писать не придется - есть unique_ptr и shared_ptr. Напишешь один using и вперед. auto pq_free = [](PGconn* pCon){ PQFree(pCon); }; // deleter коннектов using uniquer = std::unique_ptr<PGconn, decltype(pq_free)>; // владелец коннектов auto creator =[&](PGconn* pCon){ return uniquer(pCon, pq_free); }; // фабрика владельцев /* коннектимся к трём базам */ auto dbCon1 = creator(PQconnectdb(psql_connect_info1)); auto dbCon2 = creator(PQconnectdb(psql_connect_info2)); auto dbCon3 = creator(PQconnectdb(psql_connect_info3)); |
Сообщ.
#374
,
|
|
|
Цитата Qraizer @ Ада вон наполовину декларативная, хрен ты там Хелоу, ворлд напишешь, пока все контракты не обозначишь. За натурально декларативные по типу Пролога вообще молчу Декларативность как бы ортогональна контрактам и всему такому прочему и Ада даже на половину не декларативна, стандартный императив, разве что с более развитой системой типов, чем много где. Но и там есть дыры, и на Аде космические корабли бороздят просторы бетона. |
Сообщ.
#375
,
|
|
|
Так что scope-ы всё равно остаются и навсегда останутся костылями. Когда некому следить за соблюдением контрактов, всегда остаётся вероятность всплыть "Упс! "ам. Где-то раньше, где-то позже, у кого-то мало, у кого-то много, когда-то редко, когда-то часто, но вероятность всегда будет.
Бывает, что костыли дешевле, потому они и существуют в природе, но делать из костылей технологию – увольте, это детский сад. Добавлено Цитата korvin @ Ну не придирайся. Ты прекрасно понял, о чём речь. Описание контрактов всегда декларативны по своей природе. Даже обычный прототип функции в простом С декларативно описывает её контракт. Декларативность как бы ортогональна контрактам и всему такому прочему и Ада даже на половину не декларативна, стандартный императив, разве что с более развитой системой типов, чем много где Добавлено Ну и да, контракты тоже можно описать с ошибками, это не абсолютная панацея. |