LINUX.ORG.RU

Ушат помоев в сторону крестолюбов

 , , ловите наркомана,


15

14

Восседая в уютненьком кресле с чашечкой сладкого чая, внезапно ощутил приток жопной боли напополам с лирическим настроением и решил излить сию благодать куда руки дотянулись.

Последние 7 лет я пишу сугубо на C, и только под Linux (да, да -std=gnu99 и accept4, dup3, __attribute__((cleanup(dtor))) и прочие приятности, позволяющие сделать волосы шелковистее на 15.5%) и не понимаю, для чего вообще нужен C++? То, что на сишке делается красиво и элегантно, в крестах напоминает соитие парализованных дцпшников (к сожалению, утерял картинку, но именно этот образ всплывает в голове, когда вижу очередную порцию крестолапши).

Давайте посмотрим на типичного C++ разработчика: он использует STL, boost, многие любят Qt (не только для GUI), якобы чтобы «писать кроссплатформенный код». В итоге болезный не знает током ни WinAPI, ни POSIX — ничерта. Он абсолютно не разбирается, как работает целевая система, для которой пишет код! Крестокодер просто не осознает, какой лютый ужас кроется за его любимыми iostream-ами, какое лютое говно лежит в boost::filesystem::path, насколько убого-низкоуровневым является boost::asio в 2016 году.

Только крестораб может эпично обосраться и просадить производительность, забыв передавать по ссылке параметры для «горячих» функций (то есть, просто забыв написать «&» в нужном месте).

Также эти убогие завистливо смотрят на type inference в языках, проектировавшихся не как «C на стероидах», и в ответ начинают лепить template и auto не к месту, от чего код адово пухнет и даже IDE перестает его понимать.

Серьезно, просто прекратите писать на этом языке. В следующий раз, начиная новый проект, выберите java (щютка)/go/swift/rust/c. Прекратите насиловать труп и отравлять зловонием все вокруг!

Перемещено true_admin из talks

★★★★

Последнее исправление: a1batross (всего исправлений: 2)
Ответ на: комментарий от shty

«хипсторы» в треде, все въ лимузинъ!

сам такой, я наоборот для вас стараюсь, на вашем же языке писать.

alwayslate ★★
()
Ответ на: комментарий от asaw

а я говорю что Java сильно лучше ? или там C# ? так и причем тут GUI тулкиты ?

похоже у вас каша в голове, нет ?

PS говнокод пишут на всех языках, на каких то больше, на каких то меньше (в % соотношении).

alwayslate ★★
()
Ответ на: комментарий от alwayslate

а я говорю что Java сильно лучше ? или там C# ?

Ты говоришь, что Java и C# настолько лучше, что ты готов их использовать.

так и причем тут GUI тулкиты ?

При том, что ты их упомянул.

похоже у вас каша в голове, нет ?

Похоже, ты просто забыл, что говорил недавно.

tailgunner ★★★★★
()
Ответ на: комментарий от anonymous

временная переменная в операторе присваивания не нужна

Ясно, что можно без неё. Даже своп можно сделать без неё, только никому не нужно. Смысл в мерянии байтиками на стеке видят только самые йуные программисты, да и не факт, что байтики на стеке вообще будут.

не демонстрация полной версии этого оператора

А чо полную версию не выкатил? Ты же тут распинался, что это просто, как «= default» написать.

Кому нужны дебажные сборки? :-)

Они-то нужны всем, а вот производительность в них - нет.

Не переживай, это не для тебя :-)

А для кого? Сколько твоих коллег за твою короткую жизнь в них разбиралось?

И того, за нашу беседу вместо вменяемых аргументов ты выкатил:

  • кучку не относящегося к делу кудахтанья;
  • копрофильские фантазии;
  • подсчёт строк в исходниках;
  • подсчёт байтиков на стеке;
  • подсчёт производительности на -O0.

Что-нибудь ещё будет? У меня уже днищеметр зашкалил.

Esper
()
Ответ на: комментарий от Esper

Они-то нужны всем, а вот производительность в них - нет.

Мне нужна :-)

И того, за нашу беседу вместо вменяемых аргументов ты выкатил:

«Итого» пишется слитно :-) Итого: аргументов, что unique_ptr оправдан в pimpl получено не было :-)

Что-нибудь ещё будет? У меня уже днищеметр зашкалил.

Ну и выяснилось, что ты можешь давать лишь пустые комментарии и хамить :-) Лол :-)

anonymous
()
Ответ на: комментарий от rumgot

Если в 4.1 тоже по-умолчанию, то у меня на большом проекте отлично работает в плане скорости. Но, поскольку куча хеадеров, то на auto давится. Особенно если это map::iterator, а в паре еще какой-нибудь shared_ptr на какой-то хитрый интерфейс. Давится он сразу на iterator'е, не показывая поля first и second.

invy ★★★★★
()
Ответ на: комментарий от invy

Так а проверь в настройках, чего гадать. Справка ---> Модули кажется. По описываемому тобой поведению как раз больше похоже на то, что у тебя используется встроенный парсер. У меня кстати встроенный парсер не фига не отображал правильно методы при разыменовывании boost::filesystem::directory_iterator.

rumgot ★★★★★
()
Последнее исправление: rumgot (всего исправлений: 1)
Ответ на: комментарий от alwayslate

а я говорю что Java сильно лучше ? или там C# ? так и причем тут GUI тулкиты ?
похоже у вас каша в голове, нет ?

Ты не понимаешь, а каша в голове у меня - замечательно просто. Перечисленные технологии закрывают сильно больше половины рынка автоматизации в различных отраслях бизнеса. Больше 80 процентов наверное. То есть всё, что реально работает и чем пользуются, делается на них, а не на каких-то абстрактных идеальных язычках. Поэтому когда ты как-то специально выделяешь из этого ряда C++, указав на overengineering, не забывай, что представляет из себя средний уровень этого самого инженеринга в реальном мире.

asaw ★★★★★
()
Ответ на: комментарий от anonymous

Мне нужна :-)

И на сколько процентов в масштабе приложения unique_ptr в пимпле её тебе просадил?

Итого: аргументов, что unique_ptr оправдан в pimpl получено не было :-)

Как не было? С unique_ptr:

  • несколько короче;
  • проще (меньше информации надо держать в голове, почти невозможно написать забагованный код);
  • единообразней;
  • можно юзать исключения в деструкторе (то, что лично тебе это не нужно, никого не волнует).

И это против абсолютно школьных аргументов за голый указатель.

ты можешь давать лишь пустые комментарии

Почти все вменяемые аргументы выдал я. Итоги подвёл я.

и хамить

На пальцах, для дислектиков

Так что ты обделался

Нетрудно заметить, что моя фраза прямого оскорбления не содержит. То, что ты воспринял её на свой счёт - твои проблемы. Так кто начал хамить?

И вообще, единственное моё прямое оскорбление за беседу - «Пока подтверждается только твоя дислексия, балаболка.» в ответ на «Давай, обделавшийся, покажи пруф :-)». Впрочем, я уже посыпаю голову пеплом, что опустился до твоего уровня.

Esper
()
Ответ на: комментарий от tailgunner

Или имелся в виду конструктор?

Конечно, конструктор, я просто описАлся.

Esper
()
Ответ на: комментарий от Esper

И на сколько процентов в масштабе приложения unique_ptr в пимпле её тебе просадил?

Смотря какой класс :-) Чем больше объекты этого класса используются тем, больше процент стремится к 50 :-)

несколько короче;
проще (меньше информации надо держать в голове, почти невозможно написать забагованный код);
единообразней;

Все эти пункты применимы и к решениям с макросами :-) То, что ты или твои коллеги их не переносят/не любят - проблемы лично ваши :-) Препроцессор идёт в комплекте, так что - не аргумент :-)

можно юзать исключения в деструкторе (то, что лично тебе это не нужно, никого не волнует).

В конструкторе? :-) Да, это аргумент :-)

Почти все вменяемые аргументы выдал я. Итоги подвёл я.

Ну и получил контраргументы по всем пунктам, см. выше :-) Ну и добавлю, что unique_ptr в пимпле у 100 классов породит 100 классов unique_ptr<T>, что не есть хорошо :-) Зачем мне тупой код в бинарнике, если его можно избежать банальными макрами? :-)

Нетрудно заметить, что моя фраза прямого оскорбления не содержит. То, что ты воспринял её на свой счёт - твои проблемы. Так кто начал хамить?

Нет проблем :-)

Впрочем, я уже посыпаю голову пеплом, что опустился до твоего уровня.

Правильно :-) Мне тоже не приятно общаться в таком формате :-) Просто аккуратнее, ладно? :-)

anonymous
()
Ответ на: комментарий от rumgot

Справка ---> Модули кажется

О боги... как ты локализованной версией IDE можешь пользоваться...

Говорю же, то на работе, дома все по-умолчанию включено.

invy ★★★★★
()
Ответ на: комментарий от anonymous

Чем больше объекты этого класса используются тем, больше процент стремится к 50 :-)

И чем тебе те 50 процентов могут помешать при отладке?

единообразие

Все эти пункты применимы и к решениям с макросами :-)

Нет. В одних классах у тебя unique_ptr, в других - raw pointer. В одних дефолтные функции нарисованы вручную, в других - делаются макросом. Какое же там единообразие?

Препроцессор идёт в комплекте, так что - не аргумент :-)

А, например, поддержка IDE, doxygen'а и прочих полезных инструментов в комплекте к персональным NIH-макрокостылям не идёт.

Ну и добавлю, что unique_ptr в пимпле у 100 классов породит 100 классов unique_ptr<T>

Уверен? Вообще-то, есть инлайн и dead code elimination.

Esper
()
Ответ на: комментарий от Esper

И чем тебе те 50 процентов могут помешать при отладке?

Не при отладке, а при выявлении какого-нибудь тонкого бага (необязательно связанного с этими пимплами) в продакшене :-)

Нет. В одних классах у тебя unique_ptr, в других - raw pointer. В одних дефолтные функции нарисованы вручную, в других - делаются макросом. Какое же там единообразие?

А зачем мне в каких-то классах unique_ptr, если мне хватает обычных указателей? :-) Ну и раздувая твою мысль, применив однажды в проекте pimpl, его надо применять в проекте всегда, чисто для однообразия? :-)

А, например, поддержка IDE, doxygen'а и прочих полезных инструментов в комплекте к персональным NIH-макрокостылям не идёт.

Это проблема цепепе :-) До ни давних пор ни одной IDE было не под силу распарсить его ужасную контекстно-зависимую семантику, и это более чем за 30 лет :-)

Уверен? Вообще-то, есть инлайн и dead code elimination.

Проверено :-)

anonymous
()
Ответ на: комментарий от anonymous

Не при отладке, а при выявлении какого-нибудь тонкого бага (необязательно связанного с этими пимплами) в продакшене :-)

Опять же, если тормоза отладочного билда были незаметны в продакшене, то дополнительные 50 процентов тоже будут почти незаметны. Если тормоза заметны, то unique_ptr, один фиг, не главный их источник. И да, зачем вообще пихать пимпл в узкое место? На LTO надеешься?

Ну и раздувая твою мысль, применив однажды в проекте pimpl, его надо применять в проекте всегда, чисто для однообразия

Именно! Применять везде, где нужно сокрытие реализации, пимпл, а не, например, костыли вроде тех, что предлагал ТС. И применять везде, где нужно управление ресурсами, unique_ptr, а не костыли, что предлагал ты. И, предугадывая возможные возмущения, да, пимпл и unique_ptr - тоже костыли, но простые в использовании и проверенные временем.

До ни давних пор ни одной IDE было не под силу распарсить его ужасную контекстно-зависимую семантику

Мне пофиг, что было 10 лет назад. А пять лет назад, когда я писал MyClass x(, мне Qt Creator выдавал в автодополнении список конструкторов, я и сомневаюсь, что он пытался искать их в макросах.

Проверено :-)

Печально. Прям баюс теперь, что от unique_ptr'а в пимплах мои проги на винчестер влезать перестанут.

Esper
()
Ответ на: комментарий от Esper

И да, зачем вообще пихать пимпл в узкое место? На LTO надеешься?

Приходится его пихать в библиотечный код, чтобы не бухтели про бинарную несовместимость :-)

пимпл, а не, например, костыли вроде тех, что предлагал ТС

В 4-м издании The C++ Programming Language нет ни одного слова «pimpl» :-) А про то, что предлагал ТС, написано на страницах аж 2-х глав этой толстой книги :-) Мне, как бы, очевидно, где реально костыль, а где прямая поддержка со стороны языка :-) Хотя она, поддержка эта, не скрывает vtable, что я и продемонстрировал, приведя исходники :-) Что-то ТС молчит по этому поводу :-)

Мне пофиг, что было 10 лет назад. А пять лет назад, когда я писал MyClass x(, мне Qt Creator выдавал в автодополнении список конструкторов, я и сомневаюсь, что он пытался искать их в макросах.

Хочешь сказать, что приходится считаться с ограниченностью поддержки C++ в IDE, не используя макросы? :-) Ну ограничивайся, причём тут я? :-) Лол :-)

Печально. Прям баюс теперь, что от unique_ptr'а в пимплах мои проги на винчестер влезать перестанут.

Я не знаю, как скажется генерация 100500 классов unique_ptr<T> на кэшировании кода :-) Это ведь 100500 деструкторов, или ты надеешься на встраивание? :-)

anonymous
()
Ответ на: комментарий от anonymous

До ни давних пор

«Недавних» пишется через «е» и «слитно».

она, поддержка эта, не скрывает vtable, что я и продемонстрировал, приведя исходники :-)

Ты продемонстрировал, что при желании ABI можно сломать. И всё.

tailgunner ★★★★★
()
Последнее исправление: tailgunner (всего исправлений: 1)
Ответ на: комментарий от tailgunner

Ты продемонстрировал, что при желании ABI можно сломать. И всё.

Покажи как не сломать :-) Есть абстрактный класс, есть функция создания реализации этого класса, есть приложение, которое линкуется к библиотеке с абстрактным классом работает через указатель на объект абстрактного класса :-) (Ранее я говорил, что добавлять виртуальные функции можно, но только в конец, на что получил возражения :-)) Итак, как не сломать ABI, добавляя виртуальную функцию в абстрактный класс? :-)

anonymous
()

Ну ок, посоветуй с чего начать. А то в прошлый раз на мою просьбу научить программированию отозвались только C++-ники

ZenitharChampion ★★★★★
()
Ответ на: комментарий от tailgunner

«Недавних» пишется через «е» и «слитно».

Да, да, как и «итого» :-)

anonymous
()
Ответ на: комментарий от anonymous

Ранее я говорил, что добавлять виртуальные функции можно, но только в конец, на что получил возражения

Оказывается, ты и сам знаешь.

«Недавних» пишется через «е» и «слитно».

Да, да, как и «итого» :-)

Если ты пишешь «итого» через «е», у меня для тебя плохие новости.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Оказывается, ты и сам знаешь.

Об это уже было сказано, ты просто не увидел или не понял :-)

Если ты пишешь «итого» через «е», у меня для тебя плохие новости.

Лол :-)

anonymous
()
Ответ на: комментарий от anonymous

Оказывается, ты и сам знаешь.

Об это уже было сказано, ты просто не увидел или не понял :-)

Я понял, что ты специально хочешь сломать ABI, чтобы потом жаловаться на плохой Си++.

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

Я понял, что ты специально хочешь сломать ABI, чтобы потом жаловаться на плохой Си++.

Нет :-) C++ - очень хороший язык :-) Просто мне не нравится то, что виртуальные функции можно добавлять лишь в конец vtable :-) Как бы это не красиво потом выглядит в заголовке; как сказал бы Esper, - «не однообразно» :-) А так, решение на абстрактных классах, к тому же, быстрее почти на 10-20% :-) Вот, один товарищ замерил :-)

anonymous
()
Ответ на: комментарий от ZenitharChampion

Ну ок, посоветуй с чего начать.

Берешь K&R и начинаешь. ПРОФИТ!

Oxdeadbeef ★★★
()
Ответ на: комментарий от tailgunner

Ты продемонстрировал, что при желании ABI можно сломать. И всё.

Да, и кстати, цепепе таки vtable не скрывает :-) Иначе бы то, что продемонстрировал я, не поломало бы ABI :-)

anonymous
()
Ответ на: комментарий от tailgunner

Ты говоришь, что Java и C# настолько лучше, что ты готов их использовать.

оно проще и с ним быстрее, я использовать не то чтобы готов, но найти людей которые быстро сделают на Java/C# быстрее и дешевле будет итого. В той части работы где мне надо что то вроде proof of concept сделать Java/C# не годится, как и C++, остальная часть работы это не кодинг.

При том, что ты их упомянул.

дак читать надо, я не про то что их вагон и тележка, а то что в Qt например свое понимание как надо юзать плюсы, в другом проекте не Qt и не GUI, другое и тд. Qt просто как яркий тому пример, и таки да, GUI тут нипричем. А то что тулкитов море - это даже хорошо.

Похоже, ты просто забыл, что говорил недавно.

Похоже, ты просто прочел, что хотел прочитать.

alwayslate ★★
()
Ответ на: комментарий от asaw

Поэтому когда ты как-то специально выделяешь из этого ряда C++, указав на overengineering, не забывай, что представляет из себя средний уровень этого самого инженеринга в реальном мире.

представляю, дальше что ? и теперь что оно от этого становится гладким и шелковистым ?

alwayslate ★★
()
Ответ на: комментарий от anonymous

Добавление вирт. функции не работает, как и ожидалось :-)

Все работает вполне ожидаемо: ты поменял интерфейс. Если тебе ну прямо позарез нужна дополнительная виртуальная функция, то правильный путь:

class S_impl_base : public S {
public:
  virtual void f3() = 0;
};

class S_impl1 : public S_impl_base { ... };
class S_impl2 : public S_impl_base { ... };
...

Публичный интерфейс должен быть незыблем. Меняется публичный интерфейс => меняется версия библиотеки.

Я же говорю: все проблемы плюсоразработчиков идут от того, что они не понимают C++ от слова «совсем».

Также у меня есть еще пара замечаний:

  1. Если нужно сокрытие реализации внутри библиотеки, поставляющейся как shared object, за стабильностью интерфейсов нужно следить внимательнейшим образом. pimpl, по сути своей, это просто махинации поверх неопределенного типа
  2. Такое сокрытие есть в C, и оно на пару порядков элегантнее. За примерами в libcurl и даже в glib (см как они скрыли «детали реализации» массива. Это по сути адаптация сишной техники. Итого пишешь pimpl => ты пейсатель на C с классами.
kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от anonymous

Вот, один товарищ замерил :-)
Anyone who observed me spotting a Pimpl in code will know that I am not a fan of this idom. Its intend is to reduce build times by using a design pattern to move implementation details out of headers — a workaround for C++s misfeature of by default needing a recompile even for changing implementation details only without changing the public interface

Ммм, как сладенько: сначала мы делаем темплейты, потом они тормозят, мы пытаемся придумать extern template, но вендоры не осиливают, вместо этого начинаются костыли с precompiled headers (кстати, кто-то еще помнит, что в gcc phc — это дамп внутренней структуры, да такой, что между версиями компилятора проблемы с переносимостью). В итоге несчастные разработчики придумывают офигеть какой костыль.

В то же время, на C мы просто пишем.

struct my_struct {
  /* fields */
};

void my_struct_init(struct my_struct *s);

/* или */
struct my_struct; /* 100% opaque structure */
struct my_struct* my_struct_new();
И весь код, как и ожидается, лежит в *.c.

Нда, теперь и мне начинает казаться, что C++ помрет в ближайшее время с такими-то врожденными уродствами.

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

то правильный путь:

Ты предложил костыль :-) Тот же эффект достигается путём добавления функции в конец vtable :-) Собственно, ты это и сделал, только через задний проход, когда вводил аж 3 суррогатных сущности по именам S_impl_base, S_impl1, S_impl2 :-) Это решение назвать элегантным нельзя, ну вот никак :-)

За примерами в libcurl

Ну что там, opaque-поинтеры что-ли? :-) Да, это тот же pimpl, только без деструктора :-) :-)

anonymous
()
Ответ на: комментарий от kawaii_neko

В то же время, на C мы просто пишем.

Потом мы забываем вызывать my_struct_init. Еще чаще забываем вызывать my_struct_deinit. Еще, иногда, какой-нибудь дятел меняет список полей в my_struct, или просто играется с ключиками для выравнивания данных.

Аналогично, забываем дергать my_struct_new() и еще чаще забываем дергать my_struct_destroy().

Но самая мякотка-то в том, что все эти ваши любимые привычки к разбрасыванию мелких грабелек вы вполне можете сохранять и в C++. Ну, чисто если мозгов не хватает подучиться чуток.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Тот же эффект достигается путём добавления функции в конец vtable

Тебе стандарт что-то гарантирует по поводу заполнения vtable? Нет.

аж 3 суррогатных сущности

Суррогатная сущность всего одна — S_impl_base. Предполагается, что имплементации внезапно (т. е. без изменения базового интерфейса) понадобилась еще одна модификация поведения. Уж извини за резкость, но определять виртуальную функцию с единственной имплементацией — признак начала деменции.

Ну что там, opaque-поинтеры

Да.

Да, это тот же pimpl

Именно. Как я говорил, такое сокрытие реализации — это чисто сишная практика и хорошо такое работает только в сишке. В крестах это только замусоривает код лишним говном: инстанцирование unique_ptr-ов и, самое страшное, дублирование интерфейса в классе-обертке в ручном режиме.

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

Тебе стандарт что-то гарантирует по поводу заполнения vtable? Нет.

Похоже, ты прав :-) Я не помню этого в стандарте :-)

Суррогатная сущность всего одна — S_impl_base. Предполагается, что имплементации внезапно (т. е. без изменения базового интерфейса) понадобилась еще одна модификация поведения. Уж извини за резкость, но определять виртуальную функцию с единственной имплементацией — признак начала деменции.

Ты прав :-)

в крестах это только замусоривает код лишним говном: инстанцирование unique_ptr-ов

Т.е. если уж скатываться в pimpl, то unique_ptr чисто ради простоты определения деструктора, конструктора и оператора перемещения лучше не использовать, а использовать обычный указатель? :-)

дублирование интерфейса в классе-обертке в ручном режиме.

Ну за это я pimpl терпеть не могу :-) С другой стороны, мне не нравится определять в ручном режиме vtable в C :-)

anonymous
()
Ответ на: комментарий от eao197

Потом мы забываем вызывать my_struct_init. Еще чаще забываем вызывать my_struct_deinit

Слабоумным не место в разработке.

Еще, иногда, какой-нибудь дятел меняет список полей в my_struct, или просто играется с ключиками для выравнивания данных.

Есть два уровня сокрытия. И один из них — это полный черный ящик. Внутри библиотеки меняй на здоровье как хочешь.

Но самая мякотка-то в том, что все эти ваши любимые привычки к разбрасыванию мелких грабелек вы вполне можете сохранять и в C++.

Давай посчитаем накладные расходы и «грабельки» на pimpl?

  1. Дублирование интерфейса внутренней реализации в публичном классе: ведь код, использующий библиотеку, не может обратиться к pimpl напрямую. Это, кстати, пишется руками, зачастую копипастится, а этот прием порой такие баги порождает, что просто жуть. Ну и приходится уповать на оптимизатор как дело доходит до возврата сложных типов.
  2. Проблемы с копированием. Если просто написать pimpl, то нужно либо не забыть закрыть все конструкторы и операторы копирования, либо писать копирование вручную.
    MyClass a(param1), b(param2);
    a = b; // катастрофа, b лежит в руинах!
    std::cout << b << std::endl; // segfault или exception — мне лень смотреть, что происходит при разыменовании пустого unique_ptr
    
kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

В крестах это только замусоривает код лишним говном: инстанцирование unique_ptr-ов и, самое страшное, дублирование интерфейса в классе-обертке в ручном режиме.

Вам не приходило в голову, что в PImpl-е может быть так, что нет обертки? И все методы внешнего класса не обязательно делают трансляцию вызовов в методы внутреннего класса? Т.е., вместо:

// .hpp
class demo {
  struct demo_impl;
  unique_ptr<demo_impl> impl_;
public :
  demo();
  ~demo();
  void f();
};

// .cpp
struct demo_impl {
  some_data data_;
  void f() { process(data_); }
};
...
demo::f() { impl_->f(); }
Может быть вот так:
// .hpp
class demo {
  struct demo_impl;
  unique_ptr<demo_impl> impl_;
public :
  demo();
  ~demo();
  void f();
};

// .cpp
struct demo_impl {
  some_data data_;
};
...
demo::f() { process(impl_->data_); }

Или для вас это уже не православный PImpl?

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Т.е. если уж скатываться в pimpl

Лично мое мнение, которого гарантированно не совпадает с мнением крестобольшинства: если в C++ скатываешься в pimpl, меняй язык, пока не стало слишком поздно.

С другой стороны, мне не нравится определять в ручном режиме vtable в C

А vtable далеко не всегда нужны.

struct my_struct;

struct my_struct* my_struct_new(int param);
int my_struct_get_param(const struct my_struct *s);
void my_struct_do_smth(const struct my_struct *s);
void my_struct_print(const struct my_struct *s, FILE *out);
Если в какой-то момент случится, что у тебя бывают «немного различающиеся» my_struct-ы, для которых печать должна работать чуточку иначе, просто заводишь указатель на функцию печати прямо в структуре и дергаешь его в my_struct_print.

C дает огромную свободу, но грамотно ею воспользоваться сегодняшний среднестатистический разработчик не в состоянии в силу своей чрезвычайно низкой квалификации.

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

Дублирование интерфейса внутренней реализации в публичном классе

Это если с головой проблемы.

Проблемы с копированием.

Да, в C копирования нет. Нет и проблем. Прям как с блохами.

Ну и да, если у вас PImpl посредством unique_ptr, просто так вы копировать свои MyClass не сможете (в отличии от говнорекомендаций смайлодауна, задрачивающего на голые указатели).

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Или для вас это уже не православный PImpl?

pimpl не может быть «православным» по определению: это еретический богомерзкий костыль.

Я так понимаю, возражений по поводу нарушения семантики оператора присваивания не будет?

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от kawaii_neko

Лично мое мнение, которого гарантированно не совпадает с мнением крестобольшинства: если в C++ скатываешься в pimpl, меняй язык, пока не стало слишком поздно.

Учту :-)

Если в какой-то момент случится, что у тебя бывают «немного различающиеся» my_struct-ы, для которых печать должна работать чуточку иначе, просто заводишь указатель на функцию печати прямо в структуре и дергаешь его в my_struct_print.

Для простых случаев этого достаточно :-)

C дает огромную свободу, но грамотно ею воспользоваться сегодняшний среднестатистический разработчик не в состоянии в силу своей чрезвычайно низкой квалификации.

Это верно :-)

anonymous
()
Ответ на: комментарий от eao197

(в отличии от говнорекомендаций смайлодауна, задрачивающего на голые указатели).

Не беспокойся, в отличии от даунов-задротов, для которых проблема не написать в определении класса 2 строчки T(const T&) = delete, T& operator=(const T&) = delete, задрачивающие на голые указатели в этом проблем не видят :-)

anonymous
()
Ответ на: комментарий от kawaii_neko

Я так понимаю, возражений по поводу нарушения семантики оператора присваивания не будет?

Вы, блин, прикалываетесь или реально настолько тупы? Вот, посмотрите: https://godbolt.org/g/QBQYYd Если с unique_ptr внутрях вы не определяете своих операторов копирования/перемещения, то вы не можете копировать PImpl-ы.

А если определяете свои операции копирования и перемещения, то можете назначить любую семантику.

Ну и кстати говоря, по поводу «еретический богомерзкий костыль». В бытность C++03 PImpl служил не только и не столько для сокрытия деталей реализации (или для уменьшения видимости зависимостей), но и для обеспечения реализации exception safe оператора копирования для классов со сложными потрохами. В C++11/14 с move semantic с этим уже проще, но PImpl все равно для этих целей продолжает применяться.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

Вы вообще на C++ не программируете, сами мамой здесь клялись. Так что можете сочинять про себя любые небылицы.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Вы, блин, прикалываетесь или реально настолько тупы?

Переходи уже на «ты». «Вы тупы» реально тупо звучит.

Если с unique_ptr внутрях вы не определяете своих операторов копирования/перемещения, то вы не можете копировать PImpl-ы.

Ага, а вот и «закат солнца вручную» пошел. То есть, в нагрузку к лишней сущности «pimpl» идет как минимум две: 1) конструктор копирования; 2) оператор присваивания. В лучшем случае они состоят и *this->pimpl = *other.pimpl.

exception safe

Eдинственный реально работающий варинат exception safety, это:

#define throw *((nullptr*)0) = 0;
#define try *((nullptr*)0) = 0;
#define catch *((nullptr*)0) = 0;
Тут, конечно, большой простор для улучшения, чтобы ошибки все-таки из runtime сдвинуть в сторону compile time, но суть, думаю понятна: никогда и ни при каких условиях не бросать и не ловить исключения.

kawaii_neko ★★★★
() автор топика
Ответ на: комментарий от anonymous

Ну ограничивайся, причём тут я? :-)

Ну окей, поддержка ИДЕ тебе не нужна. Но расскажи, ты действительно свято веришь в то, что тебе никогда не придётся пользоваться doxygen'ом?

Это ведь 100500 деструкторов, или ты надеешься на встраивание?

Ну да. А что, зря надеюсь? И пруфы есть?

Esper
()
Ответ на: комментарий от kawaii_neko

«Вы тупы» реально тупо звучит.

Если вы думаете, что «вы» здесь употребляется из вежливости, то сильно ошибаетесь.

То есть, в нагрузку к лишней сущности «pimpl» идет как минимум две: 1) конструктор копирования; 2) оператор присваивания.

Вообще-то это идет в нагрузку ко всем классам, которые владеют, какими-то ресурсами. И, в подавляющем случае, там нужны не операции копирования, а операции перемещения.

но суть, думаю понятна: никогда и ни при каких условиях не бросать и не ловить исключения.

Да, очередной дятел.

eao197 ★★★★★
()
Ответ на: комментарий от Esper

Ну окей, поддержка ИДЕ тебе не нужна. Но расскажи, ты действительно свято веришь в то, что тебе никогда не придётся пользоваться doxygen'ом?

А что, doxygen не умеет генерить документацию для макросов? :-)

Ну да. А что, зря надеюсь? И пруфы есть?

Может и не зря :-)

Но вот отладочный бинарь пухнет прилично :-) На порядок :-) Зацени: unique_ptr:

#include <memory>

struct S1 {}; struct S2 {}; struct S3 {}; struct S4 {}; struct S5 {};
struct S6 {}; struct S7 {}; struct S8 {}; struct S9 {}; struct S10 {};

#define EXPR(T) { std::unique_ptr<T> o{new T()}; }

int main(int argc, char *argv[])
{
  EXPR(S1); EXPR(S2); EXPR(S3); EXPR(S4); EXPR(S5);
  EXPR(S6); EXPR(S7); EXPR(S8); EXPR(S9); EXPR(S10);
  return 0;
}

голый указатель

struct S1 {}; struct S2 {}; struct S3 {}; struct S4 {}; struct S5 {};
struct S6 {}; struct S7 {}; struct S8 {}; struct S9 {}; struct S10 {};

#define EXPR(T) { auto o = new T(); }

int main(int argc, char *argv[])
{
  EXPR(S1); EXPR(S2); EXPR(S3); EXPR(S4); EXPR(S5);
  EXPR(S6); EXPR(S7); EXPR(S8); EXPR(S9); EXPR(S10);
  return 0;
}

$ g++ -g -O2 -std=c++14 -ounique unique.cpp
$ g++ -g -O2 -std=c++14 -oraw raw.cpp
$ ls -s raw unique
 12 raw  120 unique
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.