Здравствуйте, smeeld, Вы писали:
S>И как же в крупных проектах на Си и Си c классами обходятся без этих понтов и заклинаний aka std::move, std::swap и прочих trivially_constructable?
С большим трудом. С опасностью подорваться на говнокоде на каждом шагу. С древней кодобазой, на 80% состоящей из велосипедов в которых уже никто не разбирается.
Кстати, обратите внимание, какие замечательные короткие имена нам предлагают использовать для констант. На пол-экрана. А чо такова, мониторы-то теперь широкие?
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, AlexRK, Вы писали:
ARK>>И дизреспект so5team за тупые наезды, хамство и переходы на личности.
S>Простите мне мой французский, но когда человек безапеляционно заявляет что:
S>* пространства имен не решают ни одной проблемы, а взамен можно использовать префиксы;
Именно так господа. В с++ пространства имен не более чем синтаксический сахар без которого прекрасно можно жить и многие так и делают.
Языку больше нужна полноценная поддержка библиотек которая сейчас полностью отсутствует. Нет ни стандартного формата проектов, ни механизмов поддержки библиотек таких как: интерфейсы, общий базовый класс для полиморфных объектов, отказ от препроцессора и т.д и т.п. В результате многие библиотеки для С++ делают header only, что является форменным извращением. А полноценные невозможно установить и использовать без танцев с бубном.
В одной из книг страуструп посетовал, что они ждали появления тысяч библиотек классов для С++, а этого не произошло. А что он собственно сделал для того чтобы это произошло? Наводнил язык бесполезными и недоделанными фичами. И неймспейсы одна из них.
S>* iostreams были сделаны "на спор";
Именно так. Какая разница, что страуструп спорил не с человеком а с книгой? Это уже называется не разработка, а шоу нарциссо. Удивительно что находятся программисты которые пытаются получившийся продукт на хлеб мазать.
S>* STL попал в стандарт минуя продакшен;
Тот продакшон может уже давным давно разорился и даже эха не осталось. А в уважающих себя продакшонах к stl относились весьма настороженно
The Unreal Engine's avoidance of the C++ standard library's containers is primarily historical. C++ was standardized in 1998, the same year we shipped the first Unreal Engine game.
Back then, the standard libraries were controversial, poorly-implemented, and very inconsistent between platforms. They made very aggressive use of new C++ features that **hadn't yet been production-proven**, and had some significant problems interoperating with C libraries. For example, std::vector wasn't guaranteed to be contiguous, so passing an array to a C library like DirectX could potentially involve creating a temporary copy of it.
S>* что размеры и индексы могут быть представлены только знаковыми целыми и никак иначе;
Именно так! Потенциальные грабли нужно устранять, даже ценой двухкратного сокращения диапазона индексов. С++ же спроектирован в погоне за ветряными мельницами, чтобы каждая написанная строка кода давалась программисту кровью и потом. Чтобы вместо того чтобы просто писать работающий код, программист обдумывал бы каждый оператор, не будет ли там смешанной арифметики, переполнения и т.д и т.п.
Человек который имеет другую точку зрения, конечно имеет на нее полное право, но по сути является садомазохистом и не подходит для принятия общественно значимых решений по моральным качествам.
S>* не может привести ни одного внятного примера в обоснование своего же тезиса,
Тезисы я приводил и не один раз. может просто шоры нужно снять с глаз?
S>Технический спор -- это обмен аргументами. Когда же вместо аргументов используется "Конечно, считаю правильным и единственно верным." и "Да и сама проблема не сложнее выеденного яйца." + "Нет никаких проблем чтобы сделать опережающее описание следующим образом:" (при том, что здесь уже была цитата от человека, который описывал, как комитет обсуждал этот вопрос и почему решил ничего не менять, т.к. все далеко не так просто, как кажется Kluev-у), то остается только указать человеку на его поведение. Т.е. перейти на личности.
Комитет вообще-то решил прорабатывать дальше. Как обычно двинули проблему в долгий ящик.
Здравствуйте, so5team, Вы писали:
S>Видите ли какое дело: C++20 рано или поздно будет освоен. Не говоря уже о молодежи, которая может начинать прямо с C++17. И количество подрывов будет сокращаться с каждым месяцем опыта с новым C++.
Молодёжь принудительно подсаживают на Go, python, rust, JS и прочую хипстоту. Зачем городить что-то на C++, когда можно модно и молодёжно сваять на JS+Electron? Так рассуждают везде, кроме серверов, железок и тырпрайза. С С++ играют только задроты, которым делать нечего и которых на работу не берут. С++ всё больше и с ускорением скатывается к туда же, где прозябает Haskel. На серверах и железках доминирует чистый Cи, и будет, пока линуксы и прочие оракелы на Cи написаны, а замены им не видно. А в тырпрайзе C++ и не было никогда, там java балом правит.
Здравствуйте, chaotic-kotik, Вы писали:
CK>Здравствуйте, lpd, Вы писали:
lpd>>Вообще идея связывать время жизни переменной и какие-то операции по освобождению ресурсов довольно сомнительная. Время жизни переменной — это исключительно синтаксическая вещь, а освобождение ресурсов — императивная операция. И писать обертки над функциями только чтобы создать временную переменную, рассчитывая что где-то компилятор ее удалит, это удалять зубы через нос.
CK>как раз наоборот, компилятор не забудет удалить, а вот кое кто предпочитает писать код с утечками, потому что так "проще"
Я понимаю, вот совпало, что переменные на стеке компилятор когда-нибудь удаляет, и решили приспособить это дело под освобождение памяти. Это решение явно притянуто за уши, этим мне и не нравится. Ботинок тоже всегда под рукой, и из него вода не выльется. Но чай-то мы пьем из специальных чашек, а не из обуви. Хотя что будет, если авторитетные киноактеры завтра начнут пить из обуви, я не берусь предсказать.
Точно также освобождение памяти или ресурсов, искусственно привязанных к переменной, в ее деструкторе — это хак чистой воды, лишенный всякой логики. Если ты этого не видишь, то мои аргументы будут бесполезны.
CK>ну вот чуть выше я предложил пример: CK>Если ты попробуешь переписать код так, чтобы этого избежать, то получится жуткая каша, с unique_ptr такой проблемы нет
Я это видел, вариант с прямой проверкой результата вызова оператора new или malloc() кашей не считаю. То, что запись auto x = std::make_unique<X>(); более короткая, не значит что она лучше.
CK>- создание объектов в GC языках — очень быстрая операция, удаление тоже (так как у большинства объектов финализаторы пустые), тормозит stop the world фаза сборки мусора, когда GC останавливает все потоки и помечает все достижимые объекты
Если массовые объекты будут удалены вручную, то stop of the world будет быстрее, о чем я и пишу. В тех редких случаях когда этого недостаточно, можно использовать другие способы управления памятью.
CK>- free/delete в современных плюсах, как я уже писал, это code smell, попробуй найди хоть одну причину для их использования, кроме личных предпочтений — ничего не получится, т.к. для любого кейса найдется более подходящий и безопасный вариант нежели new/delete или же malloc/free
Ну вот десятки лет пока умные указатели не встроили в С++, все (в том числе программисты получше Страуструпа и других С++ников) знали про умные указатели, и почти никто ими не пользовался, кроме как когда они реально были нужны для учета ссылок. А как только Майерс с фанатиками начали пропагандировать unique_ptr<>/shared_ptr<>, сразу выяснилось, что обычный free() code smell. В то время как подавляющее большинство программистов пользуются Java/C# с GC и не страдают этой длиннословной фигней, которую нам впаривают создатели современного С++.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, LaptevVV, Вы писали:
LVV>Была такая шутка в советское время по поводу разработки языков программирования... LVV>Лучшие языки получались у одиночек.
Не только языки. Хочешь угробить дело -- создай комитет.
Здравствуйте, Kluev, Вы писали:
S>>И где это нужно? Ну, за исключением кидания какашками на форуме?
K>Грубо говоря весь С++ это собрание ненужных и недоделанных вещей. Но речь не об этом.
Если речь не об этом, то зачем вы вновь это повторяете?
Грубо говоря, у вас цель донести до окружающих свое мнение о том, что C++ говно. Спасибо, но не нужно. Во-первых, вы не оригинальны. Во-вторых, ваше мнение не интересно. В-третьих, высказывание этого факта ничего не меняет.
K>В язык ввели вложенные классы как минимум с С++98. И 20 чертовых лет не могут сделать для них опережающее описание (forward declaration) чтобы ими можно было полноценно пользоваться.
О каком полноценном использовании вы говорите, если вы даже не можете одного простого примера того, где это было бы реально нужно, привести не можете?
По сути же вложенные классы были в языке еще до C++98. И до появления в языке пространств имен использование вложенных классов имело большой смысл, т.к. объемлющий класс выступал в качестве пространства имен. Соответственно, вложенные классы помогали избежать засорения глобального пространства имен.
Но после того, как в языке повсеместно стали доступны пространства имен, надобность во вложенных классах сильно снизилась. И очень тяжело найти примеры того, где бы опережающее объявление вложенного класса было бы нужно. И где бы нельзя было выйти из ситуации с помощью вспомогательных пространств имен.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>а со знаковыми вы уйдете в отрицательную область невалидных индексов.
S>Кто вам это гарантировал?
программист может сам себе гарантировать, в платформозависимом решении. это вполне оправдано. а если вы думаете что ваши программы будут выполнятся вечно на всех новых платформах и новом железе, то я вас расстрою. еще при нашей жизни от них и эха не останется.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>Например iostream. По словам Страуструпа была написанная кем-то на спор.
S>Цитату бы.
Это было в книге Страуструпа "язык С++" или "дизайн и эволюция С++" точно не помню. Со слов Старуструпа, один персонаж утверждал, что средствами языка нельзя сделать нормальную библиотеку ввода вывода. В общем-то он прав т.к. для нормальной библиотеки ввода вывода в языке должна быть рефлексия. В ответ на этот вызов была написана библиотека iostream. Непродуманная студенческая поделка ограниченной функциональности. Я помню еще студентом пытался воспользоваться этим изделием для организации ввода вывода,
когда понял, что библиотека для ввода-вывода полностью не работоспособна:
std::string s = "Hello World!";
std::stringstream ss;
ss << s; // поехали
ss >> s; // приехали
как и любой здравомыслящий человек решил от поделий этого цирка шапито держатся подальше. Причем std::quoted было добавлено только в с++14, и около 20 лет программисты мучились, наступали на грабли, а сектанты все это время кричали нинужно.
K>>Или stl. Минуя продакшн сразу в стандарт.
S>Если вы не в курсе, то STL допиливался до состояния, в котором его приняли в стандарт, несколько лет. И в 1996-1997-ом годах свободные реализации STL (вроде бы от RogueWare) уже активно использовались в продакшене.
Если вы не в курсе от раннего stl-мазохизма в продакшене активно отказывались и пересаживались на собственные разработки. Это уже веский повод не торопится с добавлением такой сомнительной библиотеки.
K>>>>Приведите хоть один реальный случай случая когда нельзя было бы обойтись префиксами.
S>>>Попробуйте выразить std::chrono::milliseconds через префиксы. Или std::chrono::steady_clock::time_point. А так же попробуйте придумать на префиксах адекватную замену для, например, using namespace std::chrono_literals.
K>>Да в легкую. Например std_chrono_milliseconds.
S>Вы в очередной раз несете бред.
Нет вы. Смотрите сами. Простой пример:
//1class storage
{
class blob
{
};
};
//2namespace storage
{
class storage;
class blob;
}
//3class storage;
class storage_blob;
Из всех видов описаний только описание через вложенный класс storage::blob самое нормальное и естественное, гораздо лучше чем пространство имен storage::storage+storage::blob и лучше формы storage_blob. Но для вложенного класса нет опережающего описания и его потребуется всегда включать через #include. Т.е. чтобы в данном случае программист не написал это будет говнокодом. Написать нормально язык не позволит
K>>Что касается литералов, то это фантастически бесполезная лабуда.
S>Очередной бред.
Когда у вас в языке нет:
рефлексии
модульности
оператора возведения в степерь
нет стандартной формы библиотеки, т.е невозможно организовать стандартные репозитарии библиотек как в других языках
и т.д и т.п.
на фоне вот этих вопиющих дыр полный бред тратить усилия на такие бесполезные параши как литералы.
Здравствуйте, so5team, Вы писали:
S>С большим трудом. С опасностью подорваться на говнокоде на каждом шагу.
Пока вот это всё справедливо для распоследних C++, особенно про большой труд и опасность подорваться, только подорваться не на говнокоде, а просто на C++20 коде.
S> С древней кодобазой, на 80% состоящей из велосипедов в которых уже никто не разбирается.
99% всех промышленных программных систем, обсуживающих мир, представлено именно этим кодом. А всякие хеллоуворлды даром никому не нужны, на каком бы распрекрасном C++ они не были написаны.
Здравствуйте, Mystic Artifact, Вы писали:
MA> Топ500 использует еще 100500 всякой хрени в самых разных местах. Если им это надо — это не значит, что остальной части населения, которой >99.9% нужно вообще об этом знать. Какие выводы можно сделать из того что они используют? Да никаких.
Суть не в Топ500, а в том, что sleeld здесь регулярно высказывает свое мнение о том, что фичи современного C++ не нужны для разработки производительного кода. И в пример любит приводить древний Apache TrafficServer (бывший Yahoo TrafficServer, который получился из бывшего Inktomi Traffic Server, который начали разрабатывать хз когда), где типа нет следов ни STL, ни современного C++.
Envoy же является примером производительного решения, которое написано как раз на современном C++.
Ретроградов, типа вас с smeeld, это вряд ли в чем-то убедит. Но может быть кого-то заставит перестать брать слова smeeld на веру.
Здравствуйте, lpd, Вы писали:
lpd>Теперь покажите работающий код на современном С++, от которого не хочется тошнить.
А могли бы вы показать работающий код на C++98/03, который вы считаете эталоном качества и читаемости? Ну в качестве камертона, так сказать.
Хотя можно усложнить задачу, и попросить вас показать таковой код на чистом Си. Но это уже даже не задачка со звездочкой, а с тремя звездочками. Нельзя собеседнику по RSDN такие тяжелые просьбы высказывать.
Re: Верблюд - это лошадь, разработанная комитетом... :)))
Здравствуйте, Kluev, Вы писали:
S>>Если речь не об этом, то зачем вы вновь это повторяете?
K>А что нельзя?
Формально запретов нет. Но в этом повторении нет ни смысла, ни пользы. Посему вы зря тратите и свое, и чужое время.
S>>Грубо говоря, у вас цель донести до окружающих свое мнение о том, что C++ говно. Спасибо, но не нужно. Во-первых, вы не оригинальны. Во-вторых, ваше мнение не интересно. В-третьих, высказывание этого факта ничего не меняет.
K>Знаете, переход на личности еще можно оправдать в возрасте до 30. Дальше это инфантилизм.
Если вы здесь узрели переход на личности, то проблему инфантилизма вы так же пытаетесь искать явно не там.
K>А где реально нужны пространства имен?
Везде, что хоть сколько-нибудь отличается от студенческой лабораторной.
K>Приведите хоть один реальный случай случая когда нельзя было бы обойтись префиксами.
Попробуйте выразить std::chrono::milliseconds через префиксы. Или std::chrono::steady_clock::time_point. А так же попробуйте придумать на префиксах адекватную замену для, например, using namespace std::chrono_literals.
А еще лучше, поскольку вы вроде как всерьез заговорили про префиксы, постарайтесь хоть чем-нибудь доказать, что на вас стоит тратить время. Что вы не форумный тролль и что имеете отношение к разработке запускаемого в продакшен софта. Особенно софта, который затем будете дорабатывать и эксплуатировать не вы.
K>Новшества вводят для удобства, а не только когда реально нужно.
Именно так C++ пока и развивается. Но если ваша цель -- это лишний раз заявить, что C++ говно, то вы вряд ли это замечаете.
K>Кроме того forward declaration для вложенных классов это тот случай когда исправлять реально нужно, потому что это баг на уровне языка.
Пока вы не смогли привести ни одного примера, где бы этот баг проявлялся в полный рост. И просить, видимо, бесполезно, т.к. ваша цель -- это лишний раз завить, что C++ говно.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
S>>>Цитату бы.
K>>Это было в книге Страуструпа "язык С++" или "дизайн и эволюция С++" точно не помню.
S>Т.е. вместо цитаты опять нужно полагаться на ваши слова.
Вы не привыкли джентльменам верить на слово?
C's printf family of functions is an effective and often convenient I/O mechanism.
It is not, however, type-safe or extensible to user-defined types (classes and enumera-
tions). Consequently, I started looking for a type-safe, terse, extensible, and efficient
alternative to the printf family. Part of the inspiration came from the last page and
a half of the Ada Rationale [Ichbiah,1979], which argues that you cannot have a terse
and type-safe I/O library without special language features to support it. I took that as
a challenge. The result was the stream I/O library that was first implemented in 1984
and presented
K>>Если вы не в курсе от раннего stl-мазохизма в продакшене активно отказывались и пересаживались на собственные разработки. Это уже веский повод не торопится с добавлением такой сомнительной библиотеки.
S>В курсе. Даже в курсе причин, по которым это происходило. Самой важной из которых была отсталось большинства тогдашних компиляторов. Поэтому если нужно было делать что-нибудь серьезное и переносимое, то до начала 2000-х собственные велосипеды были самым надежным способом. Только это не потому, что STL плохой, а потому что многие компиляторы даже слова template не понимали. А из тех, что понимали, понимать могли по-разному.
Самой важной причиной является то, что stl криво спроектированная библиотека. В ней плохо практически все. Даже индекс и размер контейнера и тот умудрилось сделать unsigned создав программистам кучу проблем на ровном месте. Наличие совершенно бесполезных надуманных вещей таких как valarray выдает в ней академическую разработку, написанную для диссера или научной статьи. В качестве стандартной библиотеки языка эта экспериментальная разработка категорически не годится.
S>Третья причина -- это NIH синдром.
Знаете есть вещи хорошо сделанные, которыми приятно пользоватся и писать собственный велосипед желания не возникнет. stl напротив образчик плохого дизайна и анти-эстетики.
K>>Смотрите сами. Простой пример:
K>>
K>>//1
K>>class storage
K>>
S>Простите, а это пример чего? Почему я должен думать, что все эти описания равноценны? Если вы считаете, что второй вариант является аналогом первого, то вы что-то делаете явно не так и в первом варианте нет смысла вкладывать blob в storage.
K>>Из всех видов описаний только описание через вложенный класс storage::blob самое нормальное и естественное
S>Сразу уточним: нормальное и естественное по вашему мнению. Которое можно смело отправлять в /dev/null на основании тех перлов, которые вы наговорили ранее.
И по вашему в том числе. Нотацию с префиксами вы сами забраковали постами выше, ну а класс storage в пространстве имен storage и комментариев не требует.
K>>Но для вложенного класса нет опережающего описания и его потребуется всегда включать через #include.
S>Э... Простите, а как же тогда классический pimpl работает? S>
S>Вы либо с матчастью разберитесь. Либо дайте себе труд излагать свои мысли так, чтобы их понять можно было.
Мне трудно говорить с человеком который не понимает термин "опережающее описание (forward declaration)".
//Storage.hstruct Storage
{
struct Blob
{
};
};
Класс Storage мы можем использовать без включения хедера Storage.h для этого нужно опережающее описание
struct Storage;
void foo(Stroage *stg);
С вложенным классом Storage::Blob такой номер не пройдет т.к. в языке С++ нет механизма опережающих описаний. Это баг уровня языка который нужно исправлять. Как бы вы тут не распинались, что это и не нужно.
S>Только на моей памяти:
S>* в C++ не было ни исключений, ни пространств имен, ни шаблонов; S>* в C++ не было ни шаблонов с переменным количеством параметров, ни лямбда-функций, ни move-semantic-и, ни регулярных выражений; S>* в С++ не было ни модульности, ни рефлексии, ни менеджера пакетов...
S>Вы сами можете подставить в этот список отметку "сейчас мы здесь". И можно со 100% уверенностью сказать что когда в C++ завезут модули, рефлексию, сильно обогатят стандартную билиотеку и в конце-концов выживет всего один де-факто стандартный менеджер пакетов, то персонажи вроде вас все равно будут перечислять то, что им должны обязательно дать вот прямо сейчас и бесплатно просто по праву того, что они соизволили обратить свой взгляд на C++.
Ложечка хороша к обеду. Вы можете не дожить до того момента когда в С++ завезут все что нужно. Или С++ не доживет.
То с какой скоростью и как комитет проектирует этот язык напоминает издевательство. Было бы честнее либо заморозить С++ в актуальной версии и начать новый С++2.0 несовместимый со старым как это сделали в питоне, либо совсем отказаться от разработки языка объявив его deprecated. С моей точки зрения существующий труп смысла насиловать уже не имеет.
S>По поводу литералов: если они вам не нужны (или вы ими не пользуетесь) ну так и не пользуйтесь. Зачем поливать говном то, что облегчает жизнь другим C++ разработчикам?
Эти литералы сделаны в угоду нескольким фрикам, которым не терпелось добавить в stl константы типа в минуте 60 секунд. В остальном это лишнаяя сущность и как обычно в традициях С++ совершенно беспомощная. Попбробуйте завести литерал Н/м^2 и не говорите что нинужно. Секунды завезли, а чем паскали хуже?
Здравствуйте, Kluev, Вы писали:
K>Со знаковым индексом пример всегда будет корректно работать, с беззнаковым на пустой коллекции ошибка времени выполнения.
Здравствуйте, AlexRK, Вы писали:
ARK>И дизреспект so5team за тупые наезды, хамство и переходы на личности.
Простите мне мой французский, но когда человек безапеляционно заявляет что:
* пространства имен не решают ни одной проблемы, а взамен можно использовать префиксы;
* iostreams были сделаны "на спор";
* STL попал в стандарт минуя продакшен;
* что размеры и индексы могут быть представлены только знаковыми целыми и никак иначе;
* не может привести ни одного внятного примера в обоснование своего же тезиса,
то разговор можно вести только о том, почему на высказывания этого свято уверенного в непогрешимости собственного мнения персонажа вообще стоить обращать внимание.
Технический спор -- это обмен аргументами. Когда же вместо аргументов используется "Конечно, считаю правильным и единственно верным." и "Да и сама проблема не сложнее выеденного яйца." + "Нет никаких проблем чтобы сделать опережающее описание следующим образом:" (при том, что здесь уже была цитата от человека, который описывал, как комитет обсуждал этот вопрос и почему решил ничего не менять, т.к. все далеко не так просто, как кажется Kluev-у), то остается только указать человеку на его поведение. Т.е. перейти на личности.
Ну и если кого-то в Интернете обижает, что его мнение не ценят и с ним не желают расшаркиваться в ненужных любезностях, то это странно. По меньшей мере.
S>С другой стороны, C++ и так сборная солянка всякого разного и разнообразного. Добавлять что-то новое опасно, если это реально не нужно.
Не добавлять новое, а исправлять баги. Не хотят исправлять, пусть честно объявляют вложенные классы deprecated, чтобы программисты не попадались на грабли.
Здравствуйте, Kluev, Вы писали: K>Вы просто не успеваете за линией партии. K>Начиная с С++20 вводится signed size, как обычно начинают исправлять баги спустя 20 лет K>https://en.cppreference.com/w/cpp/iterator/size
Похоже, что возвращаемый там тип далеко не int, который обычно используют любители знаковых индексов и размеров. Скорее всего, многие их них опять будут недовольны очередным стандартом.
int main()
{
std::vector<int> v = { 3, 1, 4 };
// since C++20 the signed size (ssize) can availint i = ssize(v);
for (--i; i != -1; --i) {
std::cout << v[i] << ' ';
}
std::cout << "\n" "i = " << i << '\n';
}
Выдаст предупреждение там где ssize_t не ялвяется int (т.е. практически на всех современных платформах):
prog.cc: In function 'int main()':
prog.cc:20:18: warning: conversion from 'std::common_type_t<long int, long int>' {aka 'long int'} to 'int' may change value [-Wconversion]
20 | int i = ssize(v);
| ~~~~~^~~
Proposals for which further work is encouraged:
...
Forward declarations of nested classes. This would allow things like X::A* to appear in a header without requiring a definition for X to also appear in the header (forward-declarations of X and X::A will be sufficient). EWG found the use case compelling, because currently a lot of class definitions to appear in headers only because interfaces defined in the header use pointers or references to nested classes of the type. Several details still need to be worked out. (For example, what happens if a definition of X does not appear in any other translation unit (TU)? What happens if a definition of X appears in another TU, but does not define a nested class A? What happens if it does define a nested class A, but it’s private? The answer to some or all of these may have to be “ill-formed, no diagnostic required”, because diagnosing errors of this sort would require significant linker support.)
Здравствуйте, smeeld, Вы писали:
S>Здравствуйте, T4r4sB, Вы писали:
TB>>В ++03 можно. В ++20 нет.
S>Почему это?
Килограммы говна типа std::move, std::forward, std::trivially_constructible, без которых ты не напишешь даже сраный вектор без UB который бы ПРАВИЛЬНО учитывал все возможные случаи T
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
TB>Килограммы говна типа std::move, std::forward, std::trivially_constructible, без которых ты не напишешь даже сраный вектор без UB который бы ПРАВИЛЬНО учитывал все возможные случаи T
И как же в крупных проектах на Си и Си c классами обходятся без этих понтов и заклинаний aka std::move, std::swap и прочих trivially_constructable? И при этом, там вся move семантика объектов представлена в полный рост.
Здравствуйте, smeeld, Вы писали:
S>>С большим трудом. С опасностью подорваться на говнокоде на каждом шагу.
S>Пока вот это всё справедливо для распоследних C++, особенно про большой труд и опасность подорваться,
Не знаю. На сопровождение пока разработок на распоследних C++ не попадало. А вот то, что приходится видеть в чужом легаси на чистом C или "Си с классами" -- это тихий ужас.
Вы вот, помнится, свой код когда-то показывали. Из той же категории.
Так что позвольте усомнится.
S>только подорваться не на говнокоде, а просто на C++20 коде.
Видите ли какое дело: C++20 рано или поздно будет освоен. Даже старперами вроде меня. Не говоря уже о молодежи, которая может начинать прямо с C++17. И количество подрывов будет сокращаться с каждым месяцем опыта с новым C++.
А вот древний говнокод производства зацикленных на старом добром "Си с классами" персонажей, вроде вас, так и останется говнокодом.
S>99% всех промышленных программных систем, обсуживающих мир, представлено именно этим кодом. А всякие хеллоуворлды даром никому не нужны, на каком бы распрекрасном C++ они не были написаны.
Пользователям Envoy это расскажите, к примеру. А то они так страдают от того, что не выбрали многократно помянутый вами Apache TrafficServer, что прямо спать не могут.
Здравствуйте, so5team, Вы писали:
S>Пользователям Envoy это расскажите, к примеру. А то они так страдают от того, что не выбрали многократно помянутый вами Apache TrafficServer, что прямо спать не могут.
Что это? Кто это? А, очередной хеллоуворлд с гатхаба. Неинтересно (уходит писать плагин для nginx)
Здравствуйте, Cyberax, Вы писали:
C>Envoy используется для коммутации трафика между сервисами, во многих компаниях из Top500.
Топ500 использует еще 100500 всякой хрени в самых разных местах. Если им это надо — это не значит, что остальной части населения, которой >99.9% нужно вообще об этом знать. Какие выводы можно сделать из того что они используют? Да никаких.
Здравствуйте, smeeld, Вы писали:
S>Для меня критерий прост: linux юзается везде-это не говнокод, оракел юзается везде-это не говнокод, nginx юзается везде-это не говнокод.
Здравствуйте, smeeld, Вы писали:
S>>а у вас-то квалификации хватает, чтобы отличить хеллоуворлд от не хеллоуворда?
S>Для меня критерий прост: linux юзается везде-это не говнокод, оракел юзается везде-это не говнокод, nginx юзается везде-это не говнокод. Тот примерчик, что Вы привели, юзает не индустрия, а полтора инвалида-это говнокод. Все остальные рассуждения про "красивость кода", "безопасность кода", "читаемость кода"-это рассуждения задротов, которым делать нечего. Код не может быть ни плохим, ни хорошим, он может быть юзаемым, как оракел, а может быть неюзаемым как Ваш пример. Неюзаемый код-это говнокод. Юзаемый код-это то, что выбрала индустрия, неюзаемый код-это код который выбрали полтора задрота, согласно своим личным взглядам и предпочтениям.
Здравствуйте, Cyberax, Вы писали:
C>99.99% населения Envoy и не нужен, так как у них нет сети сервисов. А там где Envoy нужен — таки nginx даже близко не поможет. И таки да, он написан очень правильно.
ОК, на современном С++ все-таки смогли написать работающий код, возможно даже эффективный.
Теперь покажите работающий код на современном С++, от которого не хочется тошнить.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, lpd, Вы писали:
S>И, что характерно, штудируют не все, и не всегда тщательно.
Тут штудировать нечего, освобождение ресурсов и другие подобные операции вполне очевидны.
S>Это говорит лишь о том, что вы слабо себе представляете, что в современном C++ можно делать с помощью RAII (да и в старом, только там несколько многословнее все).
Создать объект-обертку над функцией? Спасибо, у меня других проблем хватает, чем городить такие конструкции на ровном месте, и усложнять код.
Бог с ним с RAII, если он так нравится, это вопрос стиля. Я больше про мув-семантику, шаблоны и умные указатели писал, впрочем по-моему не раз уж спорил здесь, в том числе с вашими.
Я привел пример кода который я считаю приятно читать и писать. О вкусах спорить не буду, но надеюсь программисты в массе все же поймут что современный С++ это только для фанатиков фич языка, пытающихся все проблемы решить новым синтаксисом, а не для реального кода, в котором и без того сложностей хватает.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, lpd, Вы писали:
S>что будет, если мне потребуется вместо skb_rbtree_walk_from(skb) написать skb_rbtree_walk_from(skb+1)?
Ты наверное понимаешь, что skb — указатель, и (skb+1) в данном случае смысла не имеет.
Будет просто:
Так что непонятно в чем твоя претензия в данном случае.
S>Полагаю, разбираться в чужих макросах сильно проще, чем в чужих шаблонах.
Макросы — это всего лишь препроцессор, поэтому они проще шаблонов, как ни крути.
S>Ну и отдельный вопрос: а зачем этот макрос вообще потребовался, ведь на Си так легко и просто понятный код писать, а тут на одном for-е почему-то экономят.
Для итерации в ядре макросов много, включая обычные list, rcu, rb_tree и прочие частные for_each_process() и for_each_device(). Вообще итерация по спискам в ядре довольно специфичная через получение адреса структуры по ее полю list_head, но достаточно один раз разобраться с list, и дальше просто пользоваться остальными макросами. В любом случае если нужно разобраться в участке кода, то у макросов названия достаточно понятные, и они не затрудняют эту задачу.
Контейнеров в ядре в такой форме как в С++ нет, как и классов, — это наверное плохо, должен согласиться. Классический С++ был бы удобнее, но можно писать понятный код и с макросами. Я же не говорю, что С лучше С++98. Хотя для С легче понять где какой метод вызывается без виртуальных функций(аргумент Линуса). Также в С полегче предсказать какой бинарный код получится и разбираться в ассемблерных дампах, что в ядре является плюсом.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, lpd, Вы писали: S>А вы, наверное, не понимаете, что вместо (skb+1) может быть что угодно. Скажем (skb++). И тогда макрос развернется во что-то вроде
Никто в здравом уме не напишет (skb++), поскольку это не указатель на члены массива. Аргумент понятен, но надо понимать что пишешь, без этого все равно никак.
S>Т.е. высказанные вами предпочтения должны приниматься во внимание только при разработке ядра Linux-а, правильно?
Относительно макросов и С, да, больше про ядро ОС.
Насчет фич вроде мув-семантики и умных указателей — к С++ вообще. О вкусах не спорят, но мне не нравится что С++17 является законодателем мод(в том чисел в вакансиях), я считаю исключительно за счет эксплуатации успеха классического С++, а не из-за направления развития.
Если вам так нравится С++17 — ради бога, страдайте и мучайтесь, я же поищу проекты на обычном С++ — у меня и так проблем хватает чтобы еще ломать голову нужен мув или нет, и искать где именно неявно разлочится lock_guard.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, Ip Man, Вы писали:
IM>По-моему, комитету С++ пора на каникулы. Лет так на 10.
Тут не только комитету пора на каникулы. В соседней теме местные завсегдатаи на серьёзных щщас нахваливают откровенное говнище и оценочки друг дружке ставят: http://rsdn.org/forum/cpp/7741209
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
S>>>И где это нужно? Ну, за исключением кидания какашками на форуме?
K>>Грубо говоря весь С++ это собрание ненужных и недоделанных вещей. Но речь не об этом.
S>Если речь не об этом, то зачем вы вновь это повторяете?
А что нельзя?
S>Грубо говоря, у вас цель донести до окружающих свое мнение о том, что C++ говно. Спасибо, но не нужно. Во-первых, вы не оригинальны. Во-вторых, ваше мнение не интересно. В-третьих, высказывание этого факта ничего не меняет.
Знаете, переход на личности еще можно оправдать в возрасте до 30. Дальше это инфантилизм.
S>О каком полноценном использовании вы говорите, если вы даже не можете одного простого примера того, где это было бы реально нужно, привести не можете?
S>По сути же вложенные классы были в языке еще до C++98. И до появления в языке пространств имен использование вложенных классов имело большой смысл, т.к. объемлющий класс выступал в качестве пространства имен. Соответственно, вложенные классы помогали избежать засорения глобального пространства имен.
S>Но после того, как в языке повсеместно стали доступны пространства имен, надобность во вложенных классах сильно снизилась. И очень тяжело найти примеры того, где бы опережающее объявление вложенного класса было бы нужно. И где бы нельзя было выйти из ситуации с помощью вспомогательных пространств имен.
А где реально нужны пространства имен? Приведите хоть один реальный случай случая когда нельзя было бы обойтись префиксами. Новшества вводят для удобства, а не только когда реально нужно. Кроме того forward declaration для вложенных классов это тот случай когда исправлять реально нужно, потому что это баг на уровне языка.
Здравствуйте, B0FEE664, Вы писали:
lpd>>Вообще, файл — это абстракция ОС, управляемая по хэндлу, и не вижу смысла путать его с локальными переменными — абстракциями С++. BFE>А почему именно файл? А если речь про mutex, к примеру?
Файлы обычно первыми приводят в пример когда говорят о преимуществах RAII.
С lock_guard на мой взгляд нужно искать по коду где же этот мьютекс освободится, писать дополнительные блоки {}, поэтому проще явно написать unlock(). Да и с мьютексами обычно проблемы гораздо сложнее, чем просто забыть разлочить. Но это вопрос вкуса, не вижу большой разницы для мьютексов.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, Kluev, Вы писали:
K>Вы не привыкли джентльменам верить на слово?
Нет. Тем более, что здесь нет джентельменов.
K>C's printf family of functions is an effective and often convenient I/O mechanism. K>It is not, however, type-safe or extensible to user-defined types (classes and enumera- K>tions). Consequently, I started looking for a type-safe, terse, extensible, and efficient K>alternative to the printf family. Part of the inspiration came from the last page and K>a half of the Ada Rationale [Ichbiah,1979], which argues that you cannot have a terse K>and type-safe I/O library without special language features to support it. I took that as K>a challenge. The result was the stream I/O library that was first implemented in 1984 K>and presented
Все это сильно отличается от вашей интерпретации "По словам Страуструпа была написанная кем-то на спор." Потому что "я воспринял это как вызов" и "я сделал это наспор" сильно различаются по смыслу.
K>Самой важной причиной является то, что stl криво спроектированная библиотека. В ней плохо практически все. Даже индекс и размер контейнера и тот умудрилось сделать unsigned создав программистам кучу проблем на ровном месте. Наличие совершенно бесполезных надуманных вещей таких как valarray выдает в ней академическую разработку, написанную для диссера или научной статьи. В качестве стандартной библиотеки языка эта экспериментальная разработка категорически не годится.
Можно предположить, что вы считаете свое мнение непогрешимым и единственно правильным.
Но это не так. И авторы STL не единственные люди, которые считают, что размеры и индексы должны быть беззнаковыми.
K>Знаете есть вещи хорошо сделанные, которыми приятно пользоватся и писать собственный велосипед желания не возникнет. stl напротив образчик плохого дизайна и анти-эстетики.
Например? Неужели Qt?
K>И по вашему в том числе. Нотацию с префиксами вы сами забраковали постами выше,
Нотация с префиксами -- это негибко и немасштабируемо. Тут даже нет места для моего субъективизма.
K>ну а класс storage в пространстве имен storage и комментариев не требует.
Речь не про storage в пространстве storage. Речь про взаимоотношения storage и blob. Но для человека с такой непогрешимой верой в собственное мнение, может быть и непонятно.
K>>>Но для вложенного класса нет опережающего описания и его потребуется всегда включать через #include.
S>>Э... Простите, а как же тогда классический pimpl работает? S>>
S>>Вы либо с матчастью разберитесь. Либо дайте себе труд излагать свои мысли так, чтобы их понять можно было.
K>Мне трудно говорить с человеком который не понимает термин "опережающее описание (forward declaration)".
Пипец. А вот это что в примере, который вы, очевидно, не поняли:
class A {
struct impl;
std::unique_ptr<impl> impl_;
K>
K>struct Storage;
K>void foo(Stroage *stg);
K>
Где здесь использование?
K>С вложенным классом Storage::Blob такой номер не пройдет т.к. в языке С++ нет механизма опережающих описаний. Это баг уровня языка который нужно исправлять. Как бы вы тут не распинались, что это и не нужно.
K>
Так может вы наконец-то разродитесь примером того, где это реальная проблема?
K>То с какой скоростью и как комитет проектирует этот язык напоминает издевательство. Было бы честнее либо заморозить С++ в актуальной версии и начать новый С++2.0 несовместимый со старым как это сделали в питоне, либо совсем отказаться от разработки языка объявив его deprecated. С моей точки зрения существующий труп смысла насиловать уже не имеет.
Ну так сделайте. Кто вам мешает?
C++ развивается силами добровольцев. Если есть идеи вы можете продвинуть их в C++.
Но есть ощущение, что дальше самовлюбленного высказывания собственного бреда на RSDN, вы дальше пройти не сможете. В принципе.
K>Эти литералы сделаны в угоду нескольким фрикам, которым не терпелось добавить в stl константы типа в минуте 60 секунд.
Значит этих фриков, как минимум, на одного больше.
K>Попбробуйте завести литерал Н/м^2 и не говорите что нинужно. Секунды завезли, а чем паскали хуже?
Здравствуйте, Kluev, Вы писали:
K>С вложенным классом Storage::Blob такой номер не пройдет т.к. в языке С++ нет механизма опережающих описаний.Это баг уровня языка который нужно исправлять. Как бы вы тут не распинались, что это и не нужно.
K>
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, Kluev, Вы писали:
K>>На 16-ти битах в условиях нехватки оперативной памяти stl последнее, что понадобится программисту. Поэтому говорить, что беззнаковый индекс был сделан с оглядкой на 16-битные архитектуры. Мне кажется, что это просто смешно.
M>Ну, STMка хоть и 32ух битная, но памяти там бывает весьма мало. На младших чуть ли не 4 кб оперативы (ну, как минимум, 32 кб точно есть камешки). И ничего, вполне STL используется. Был бы C++ для C51, тоже за милую душу использовал бы stl.
M>А уж во времена становления C++ 16битные платформы вполне себе мейн стрим были. Так что твой аргумент точно фтопку
К тому времени как представили stl 32бита уже 8 лет были мейнстримом.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
S>>>Требования к софту меняются. Профилирование заставляет менять структуры данных в программе. И т.д., и т.п.
K>>Не припомню случая когда приходилось бы менять вектор на список и наоборот. Слишком разные сценарии использования. А проектировать софт с учетом возможного столкновения с небесной осью я смысла не вижу.
S>Т.е. если вы не видели, значит этого нет. Понятно. S>А такие случаи бывают. Более того, для каких-то сценариев приходится менять тип контейнера прямо в run-time, скажем, с vector на map или set.
С++ такие пируэты не поддерживает
S>А теперь возвращается к вашему "циклу на все случаи жизни". Он таковым не является. А вот если бы вы написали его на итераторах, то он бы при переходе от vector к list или deque или даже к set не поменялся бы. При этом вам было бы фиолетово, что скрывается за итератором -- знаковые индексы или беззнаковые.
Вы предлагаете один дефект stl победить с помощью другого кривого stl-костыля. Но если бы вместо оскорблений вы потрудились посмотреть дальше своего носа, то поняли бы, что за вашим предложением скрываются серьезные грабли, например при смене контейнера с list на vector итератор может стать невалидным (при вставке элемента в теле цикла). И в если случае с индексами вы бы получили ошибку компиляции и смогли бы провести ревизию кода, то с итераторами вы получите ошибку времени выполнения со всеми вытекающими последствиями. Т.е ваши методы гладки только на бумаге, а в реальной жизни гладкостью там и не пахнет. Собственно вся stl и есть бумажная концепция, малопригодная для программирования, для тех кто слаще морковки ничего в жизни не видел.
K>>>>В знаковой арифметике вы откупаетесь одним простым и эффективным if(i >= 0 && i < N)
S>>>Т.е. в вашей вселенной if(i>=0 && i<N) прощее и эффективнее if(i < N)? O_o.
K>>Имею смелость утверждать.
S>Т.е. аргументация "Kluev сказал"? Ну тогда сразу в /dev/null вместе с утверждениями "Человек который имеет другую точку зрения, конечно имеет на нее полное право, но по сути является садомазохистом и не подходит для принятия общественно значимых решений по моральным качествам."
Конечно, тех кто продвигает беззнаковые индексы в качестве общего решения гнать надо из комитетов. Вред от таких людей колоссальный, пусть в своих частных задачах хоть в даблах индексируются.
K>>Т.к. реальном мире любая операция минус в беззнаковой арифметике небезопасна и потребует проверки, любая смешанная арифметика небезопасна и потребует проверки. Написание проверок требует дополнительных мысленных усилий и ухудшает читаемость и качество кода.
S>Ох ё, детский сад, младшая ясельная группа. А знаковые у вас никогда не переполнялись? Или может вы думаете, что переполнение знаковых -- это ничего страшного, и даже не UB?
Знаковые на пустом месте не переполняются.
S>Повторюсь: поэтому-то вы "малолетний дебил" (с), который считает, что его инфантильные желания должны быть превыше всего, а его мнение безусловно является самым правильным.
K>>Правильность моего мнения доказывает большинство языков программирования на нашей планете.
S>Большинство языков программирования вообще не ставят во главу угла эффективность (или даже плюют на какие-то платформы). А вот в языках, которые на эффективность заточены, размерности и индексы беззнаковые: C, C++, Rust
Да не смешите сказками про эффективность, особенно сишные строки-то очень эффективны. С вообще был сделан из говна и палок. Думали бы об эффективности такую дрянь как препроцессор вообще бы не потащили в язык. Эффективность С++ это тоже анекдот. Ну а руст это очередной мертворожденный язык. Т.к время каркозябро-ориентированных языков требующих постоянного микроменеджемнта уже прошло.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>Перечитайте хотя бы собственные сообщения. Где там адекват?
S>Везде. В отличии от. Поскольку:
Смешно слышать такое от человека, который занимается отрицанием реальности. Напомню, что наше общение началось с отрицания вами проблемы опережающего описания вложенных классов.
Так ведь не сломано ничего. Исправлять незачем.
S>
Можете возразить, что длинно, но до auto stl-юзеры писали километровые std::map<..........., ...........>::const_iterator и не потели. Что касается литералов, то это фантастически бесполезная лабуда. Кто вообще их просил делать это?
S>...
S>Если вы не в курсе от раннего stl-мазохизма в продакшене активно отказывались и пересаживались на собственные разработки.
S>...
S>на фоне вот этих вопиющих дыр полный бред тратить усилия на такие бесполезные параши как литералы.
S>...
S>Самой важной причиной является то, что stl криво спроектированная библиотека. В ней плохо практически все.
S>...
S>Эти литералы сделаны в угоду нескольким фрикам, которым не терпелось добавить в stl константы типа в минуте 60 секунд.
S>просто таки образчики адекватности. И это ведь далеко не все, что вы решили выплеснуть на читателей ваших бредней.
Подписываюсь под каждым словом. Полнейший неадекват тащить в язык сомнительные фичи, превращающие его в помойку, в то время как в языке сотни вопиющих неисправленных проблем.
K>>Особенно примечательно ваше предложение писать все в итераторах ради "гибкости", а на самом деле прыгать по граблям перенося ошибки времени компиляции в рантайм.
S>Вы в очередной раз расписываетесь в незнании материала о котором пытаетесь рассуждать.
Вы в очередной раз неспособны заглянуть дальше своего носа. Все-таки придется пояснить
std::list<int> lst; // std::vector<int> lst;
lst.push_back(1);
lst.push_back(2);
lst.push_back(3);
lst.push_back(4);
for (auto it = lst.begin(); it != lst.end(); it++)
{
if (*it % 2)
lst.insert(it, *it);
}
Вот этот код при замене list на vector будет прекрасно компилироваться, но порождать ошибку времен выполнения. Т.е. сценарий когда вы меняете тип контейнера и все "работает" является просто пустым обещанием. В действительности итераторы только ухудшают читаемость и качество кода и создают потенциальные проблемы времени выполнения. Используя родные средства итерирования контейнера (индексы для векторов и указатели для списков) программист вынужден при смене контейнера сделать ревизию кода и исправить потенциальные проблемы.
K>>Да вы хотя-бы один пример адекватный привели, вместо пусто и сквернословия.
S>У вас неоднократно просили пример проблем с отсутствием forward declaration для вложенных классов, но вы так и не смогли (напомню, что ни на один наводящий вопрос по поводу вашего storage и storage::blob-а вы не ответили). А теперь просите, чтобы вам привели пример?
пример со storage и storage::blob был исчерпывающим, просто вы решили прикинутся шлангом и продолжить отрицание реальности.
S>Ну, OK. Пример чего вы бы хотели увидеть?
Ну вы же там грозились, что можно на мои аргументы статью опровержений написать. Вот и опровергните хотя бы один.
Re[3]: Верблюд - это лошадь, разработанная комитетом... :)))
Здравствуйте, Шахтер, Вы писали:
Ш>Здравствуйте, LaptevVV, Вы писали:
LVV>>Была такая шутка в советское время по поводу разработки языков программирования... LVV>>Лучшие языки получались у одиночек.
Ш>Не только языки. Хочешь угробить дело -- создай комитет.
Ну комитет утомил уже давно и не меня одного. У них запор сменился вербальной диареей. Все нововведения размазаны тонким слоем по трём стандартам.
Здравствуйте, smeeld, Вы писали:
S>И как же в крупных проектах на Си и Си c классами обходятся без этих понтов и заклинаний aka std::move, std::swap и прочих trivially_constructable? И при этом, там вся move семантика объектов представлена в полный рост.
Крупных проектах на Си? Не, я к вам не пойду.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, smeeld, Вы писали:
S>>Пользователям Envoy это расскажите, к примеру. А то они так страдают от того, что не выбрали многократно помянутый вами Apache TrafficServer, что прямо спать не могут.
S>Что это? Кто это? А, очередной хеллоуворлд с гатхаба.
Если исходить из того унылого кода, который вы приводили в пример, то возникает вполне обоснованный вопрос: а у вас-то квалификации хватает, чтобы отличить хеллоуворлд от не хеллоуворда? Чем докажите?
Здравствуйте, so5team, Вы писали:
S>а у вас-то квалификации хватает, чтобы отличить хеллоуворлд от не хеллоуворда?
Для меня критерий прост: linux юзается везде-это не говнокод, оракел юзается везде-это не говнокод, nginx юзается везде-это не говнокод. Тот примерчик, что Вы привели, юзает не индустрия, а полтора инвалида-это говнокод. Все остальные рассуждения про "красивость кода", "безопасность кода", "читаемость кода"-это рассуждения задротов, которым делать нечего. Код не может быть ни плохим, ни хорошим, он может быть юзаемым, как оракел, а может быть неюзаемым как Ваш пример. Неюзаемый код-это говнокод. Юзаемый код-это то, что выбрала индустрия, неюзаемый код-это код который выбрали полтора задрота, согласно своим личным взглядам и предпочтениям.
>Чем докажите?
Здравствуйте, smeeld, Вы писали:
MA>>Ядро линукса компилируется в рабочее состояние ровно одним клмпилятором. Вам это ни о чем не говорит? S>И что? Это абсолютно не важно. Этот компилятор и существует до сих пор только по причине существования упомянутого ядра.
Это говорит о многом. Это говорит, во-первых, о нежелании двигаться вперед, при том, что 10 лет как его можно собрать на ллвм с кучей патчей, а во-вторых — наличие какой-то нестандартной херни, которой там быть не должно. Вот и все. И третье, можете взять подручный экстраполятор и бежать доказывать как плохо с std::move, но в реалиях проблемы с гораздо более простыми вещами, которые почему-то как бы не простые. В четвертых, это говорит об околонулеврй переносимости кода на конкретном языке, ведь он мудряторы намудрячили такое, что оно не работает без десяти ку.
Здравствуйте, so5team, Вы писали:
S>Хотя можно усложнить задачу, и попросить вас показать таковой код на чистом Си. Но это уже даже не задачка со звездочкой, а с тремя звездочками. Нельзя собеседнику по RSDN такие тяжелые просьбы высказывать.
Ядро линукса (кроме некоторых участков вроде отдельных драйверов или sunrpc, например) вполне читабельно. Я не претендую, что все детали там знаю. Но при том огромном количестве фич которые оно содержит, обычно можно разобраться и найти концы, почему что-то не работает. Я бы впрочем и его меньше оптимизировал, начиная с тех же лишних на мой взгляд likely/unlikely во многих if. Но это лучше мув-семантики на каждом шагу лишь бы ее использовать.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Опять же, я не досконально знаю этот код, но когда нужно было разобраться в отдельных фичах, я по-крайней мере не поседел от этого вашего леса скобочек.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, lpd, Вы писали:
lpd>Ну вот тебе большая функция-кошмар плюсовика: kvm
Ну вот сходу типичное для чисто Сишного кода: как понять, где в коде этой функции можно сразу делать retun r;, а где нужно r = ...; goto out, а где r = ...; goto cancel_injection;? Посредством каких-то тайных знаний, штудирования документации, штудирования комментариев или внимательного разбирательства с кодом этой функции?
Здравствуйте, smeeld, Вы писали:
S>Здравствуйте, Mystic Artifact, Вы писали:
MA>> Это говорит о многом.
S>Это говорит прежде всего о том, что вы не учитываете политический момент. S> А именно он и определяет то, каким компилятором должен собираться линукс.
Бред какой-то. Столлман никак не может повлиять на разработку ядра,
даже на текущий процесс разработки gcc он может очень слабо повлиять.
На разработку ядра могут повлиять крупные компании, которые собственно
и оплачивают весь банкет. Но возьмем например redhat,
если посмотреть логи git llvm/clang, там куча коммитов от @redhat.com.
Здравствуйте, lpd, Вы писали:
lpd>Модифицировать функцию, не читая ее код, и не понимая что она делает — это действительно высший пилотаж, мне такое не под силу.
Между тем такое происходит сплошь и рядом: есть функция, которая перед выполнением некого главного действия X выполняет серию проверок и подготовительных действий P1, P2, ..., Pn. Спустя какое-то время выясняется, что между Pi и P(i+1) нужно вставить еще и P(i'). Которое может завершится неудачно и в случае ошибки нужно сделать преждевременный возврат.
Когда пишется нормальный код, то можно просто сделать return.
Когда все, что есть в вашем распоряжении -- это чистая ламповая Сишечка с goto err, то да, пока не проштудируешь простыню на 10 экранов, добавить P(i') не получится.
И, что характерно, штудируют не все, и не всегда тщательно.
lpd>Ну и в конкретно этом примере RAII помог бы слабо, т.к. это не освобождение ресурса, а вызов специальных функций, и в лоб по С++ному ничего тут не сделать.
Это говорит лишь о том, что вы слабо себе представляете, что в современном C++ можно делать с помощью RAII (да и в старом, только там несколько многословнее все).
что будет, если мне потребуется вместо skb_rbtree_walk_from(skb) написать skb_rbtree_walk_from(skb++)?
Полагаю, разбираться в чужих макросах сильно проще, чем в чужих шаблонах.
Ну и отдельный вопрос: а зачем этот макрос вообще потребовался, ведь на Си так легко и просто понятный код писать, а тут на одном for-е почему-то экономят.
Здравствуйте, lpd, Вы писали:
S>>А вы, наверное, не понимаете, что вместо (skb+1) может быть что угодно. Скажем (skb++). И тогда макрос развернется во что-то вроде
lpd>Никто в здравом уме не напишет (skb++), поскольку это не указатель на члены массива. Аргумент понятен, но надо понимать что пишешь, без этого все равно никак.
ИМХО, в любой нетривиальной программе количество вещей, которые желательно было бы понимать, очень быстро превышает возможности средней руки разработчика. Мои так точно. Поэтому чем больше помощи от компилятора, тем лучше.
lpd>О вкусах не спорят, но мне не нравится что С++17 является законодателем мод(в том чисел в вакансиях),
Интересно, где это C++17 уже является законодателем мод?
lpd>я считаю исключительно за счет эксплуатации успеха классического С++, а не из-за направления развития.
Многие вещи, которые вы тут подвергаете обструкции, появились еще в C++11, а C++17 только сделал C++ лучше. И не будь в свое время C++11, то не понятно, насколько был бы востребован C++ сейчас вообще.
lpd>Если вам так нравится С++17 — ради бога, страдайте и мучайтесь, я же поищу проекты на обычном С++ — у меня и так проблем хватает чтобы еще ломать голову нужен мув или нет, и искать где именно неявно разлочится lock_guard.
Так для lock_guard не нужен ни C++17, ни даже C++11. Этой штукой во всю пользовались еще во времена предшествовавшие C++98. Вы как-то непоследовательны: то для вас C++98 хорош, то вы RAII (включая lock_guard-ы) в топку отправляете...
Здравствуйте, YuriV, Вы писали:
Ш>>Не только языки. Хочешь угробить дело -- создай комитет. YV>Ну комитет утомил уже давно и не меня одного. У них запор сменился вербальной диареей. Все нововведения размазаны тонким слоем по трём стандартам.
Неужели народ начал что-то подозревать?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>Пользуясь случаем спрошу как в современном С++ сделать опережающее описание вложенного класса?
S>Ответ будет зависеть от того, что вы понимаете под "опережающее описание вложенного класса" и того, зачем вам это нужно.
Со времен си с классами не могут исправить. Это я к тому, что современный С++ это скорее смертельно больной язык через который растут мелкобуквенные stl-метастазы, нежели что-то современное.
Здравствуйте, lpd, Вы писали:
S>>Не, так не пойдет. Дайте, пожалуйста, ссылку на конкретный фрагмент кода. lpd>Ну вот тебе большая функция-кошмар плюсовика: kvm
Зачем там goto out; если можно просто написать return r; ?
Почему функция возвращает int, а не bool?
Почему r не инициализирована при объявлении? Экономим? Тогда почему прямо не возвращать константы через return?
__builtin_expect — это вообще за рамками языка С. А вот в С++ это вроде бы добавили [likely]] / [unlikely]] (никогда не пользовался).
Здравствуйте, so5team, Вы писали:
K>>Знаете, переход на личности еще можно оправдать в возрасте до 30. Дальше это инфантилизм.
S>Если вы здесь узрели переход на личности, то проблему инфантилизма вы так же пытаетесь искать явно не там.
Я конечно в курсе что в С++ нет рефлексии, но это качество каждый может развить у себя самостоятельно.
K>>А где реально нужны пространства имен?
S>Везде, что хоть сколько-нибудь отличается от студенческой лабораторной.
Смешно, но именно из студенческих лабораторий мелкобуквенная метастаза попала прямо в стандарт С++. Например iostream. По словам Страуструпа была написанная кем-то на спор. Или stl. Минуя продакшн сразу в стандарт.
K>>Приведите хоть один реальный случай случая когда нельзя было бы обойтись префиксами.
S>Попробуйте выразить std::chrono::milliseconds через префиксы. Или std::chrono::steady_clock::time_point. А так же попробуйте придумать на префиксах адекватную замену для, например, using namespace std::chrono_literals.
Да в легкую. Например std_chrono_milliseconds. Можете возразить, что длинно, но до auto stl-юзеры писали километровые std::map<..........., ...........>::const_iterator и не потели. Что касается литералов, то это фантастически бесполезная лабуда. Кто вообще их просил делать это? Люди ждут десятилетиями рефлексию, модульность, исправление дыр в языке и т.п, вместо этого комитет выпускает "литералы". Ей Богу хочется покрутить пальцем у виска.
S>А еще лучше, поскольку вы вроде как всерьез заговорили про префиксы, постарайтесь хоть чем-нибудь доказать, что на вас стоит тратить время. Что вы не форумный тролль и что имеете отношение к разработке запускаемого в продакшен софта. Особенно софта, который затем будете дорабатывать и эксплуатировать не вы.
Вы опять на личности хотите перейти? Развивайте рефлексию. В С++ мы ее все равно не дождемся
K>>Новшества вводят для удобства, а не только когда реально нужно.
S>Именно так C++ пока и развивается. Но если ваша цель -- это лишний раз заявить, что C++ говно, то вы вряд ли это замечаете.
K>>Кроме того forward declaration для вложенных классов это тот случай когда исправлять реально нужно, потому что это баг на уровне языка.
S>Пока вы не смогли привести ни одного примера, где бы этот баг проявлялся в полный рост. И просить, видимо, бесполезно, т.к. ваша цель -- это лишний раз завить, что C++ говно.
Я вам привел в пример один из неисправленных дефектов языка. Про говно и нинужно вы сами начали писать.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, lpd, Вы писали:
BFE>Но ведь ровно наоборот, если у вас в коде есть явные unlock(), то придётся просматривать весь код в поисках не только unlock(), но и всех выходов из функции.
Ну не знаю, мне проще явно написать unlock(), чем искать где закрывается нужный блок. Но это вопрос вкуса, мне не принципиально.
lpd>>Да и с мьютексами обычно проблемы гораздо сложнее, чем просто забыть разлочить. Но это вопрос вкуса, не вижу большой разницы для мьютексов.
BFE>Ну не знаю. У меня с мьютексами вообще никаких проблем никогда не было, хотя все приложения за последние 15 лет — многопоточные. Если у вас проблемы с мьютексами, значит у вас в архитектуре что-то не правильно написано.
В последний раз, когда я писал многопоточный сервер на С++, я пожалел, что возился с мьютексами, а не использовал сообщения или акторов. Вообще, с мьютексами проблем много может быть. Если ты такие проблемы не встречал, значит либо у вас очень опытный и походивший по граблям архитектор, либо логика проекта была простая, а сам код не очень многопоточный.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, Kluev, Вы писали:
S>>Цитату бы.
K>Это было в книге Страуструпа "язык С++" или "дизайн и эволюция С++" точно не помню.
Т.е. вместо цитаты опять нужно полагаться на ваши слова.
S>>Если вы не в курсе, то STL допиливался до состояния, в котором его приняли в стандарт, несколько лет. И в 1996-1997-ом годах свободные реализации STL (вроде бы от RogueWare) уже активно использовались в продакшене.
K>Если вы не в курсе от раннего stl-мазохизма в продакшене активно отказывались и пересаживались на собственные разработки. Это уже веский повод не торопится с добавлением такой сомнительной библиотеки.
В курсе. Даже в курсе причин, по которым это происходило. Самой важной из которых была отсталось большинства тогдашних компиляторов. Поэтому если нужно было делать что-нибудь серьезное и переносимое, то до начала 2000-х собственные велосипеды были самым надежным способом. Только это не потому, что STL плохой, а потому что многие компиляторы даже слова template не понимали. А из тех, что понимали, понимать могли по-разному.
Вторая причина, по которой от STL (или кусков STL) отказываются до сих пор -- это то, что нельзя сделать универсальный инструмент, который эффективен всегда. Поэтому в каких-то конкретных условиях нужно предпочесть что-то стороннее функционалу из STL (яркие примеры std::unordered_map и std::regex).
Третья причина -- это NIH синдром.
K>Смотрите сами. Простой пример:
K>
K>//1
K>class storage
K>{
K> class blob
K> {
K> };
K>};
K>//2
K>namespace storage
K>{
K> class storage;
K> class blob;
K>}
K>//3
K>class storage;
K>class storage_blob;
K>
Простите, а это пример чего? Почему я должен думать, что все эти описания равноценны? Если вы считаете, что второй вариант является аналогом первого, то вы что-то делаете явно не так и в первом варианте нет смысла вкладывать blob в storage.
K>Из всех видов описаний только описание через вложенный класс storage::blob самое нормальное и естественное
Сразу уточним: нормальное и естественное по вашему мнению. Которое можно смело отправлять в /dev/null на основании тех перлов, которые вы наговорили ранее.
K>Но для вложенного класса нет опережающего описания и его потребуется всегда включать через #include.
Э... Простите, а как же тогда классический pimpl работает?
class A {
struct impl;
std::unique_ptr<impl> impl_;
private:
~A();
...
};
Вы либо с матчастью разберитесь. Либо дайте себе труд излагать свои мысли так, чтобы их понять можно было.
K>Когда у вас в языке нет: K>рефлексии K>модульности K>оператора возведения в степерь K>нет стандартной формы библиотеки, т.е невозможно организовать стандартные репозитарии библиотек как в других языках K>и т.д и т.п.
K>на фоне вот этих вопиющих дыр полный бред тратить усилия на такие бесполезные параши как литералы.
Только на моей памяти:
* в C++ не было ни исключений, ни пространств имен, ни шаблонов;
* в C++ не было ни шаблонов с переменным количеством параметров, ни лямбда-функций, ни move-semantic-и, ни регулярных выражений;
* в С++ не было ни модульности, ни рефлексии, ни менеджера пакетов...
Вы сами можете подставить в этот список отметку "сейчас мы здесь". И можно со 100% уверенностью сказать что когда в C++ завезут модули, рефлексию, сильно обогатят стандартную билиотеку и в конце-концов выживет всего один де-факто стандартный менеджер пакетов, то персонажи вроде вас все равно будут перечислять то, что им должны обязательно дать вот прямо сейчас и бесплатно просто по праву того, что они соизволили обратить свой взгляд на C++.
По поводу литералов: если они вам не нужны (или вы ими не пользуетесь) ну так и не пользуйтесь. Зачем поливать говном то, что облегчает жизнь другим C++ разработчикам?
Здравствуйте, Kluev, Вы писали:
K>Когда у вас в языке нет: K>рефлексии
А можно пример продукта, где широко используется рефлексия и который используется более 10 лет?
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Kluev, Вы писали:
K>>Когда у вас в языке нет: K>>рефлексии BFE>А можно пример продукта, где широко используется рефлексия и который используется более 10 лет?
Здравствуйте, B0FEE664, Вы писали: BFE>Допустим. Повторюсь: можете назвать продукт (не язык, а программу), где широко используется рефлексия и который используется более 10 лет?
В Java фреймворках используется, не в курсе что ли? И софта на них может больше, чем на С++.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>Конечно, считаю правильным и единственно верным.
S>На этих словах смыл разговора с вами окончательно пропал. Бесполезно объяснять что-то персонажам, не допускающим существование альтернативных точек зрения.
S>Тем более, что даже примеров кода из вас вытащить не представляется возможным.
Примеров было достаточно. Да и сама проблема не сложнее выеденного яйца.
Здравствуйте, lpd, Вы писали:
BFE>>Допустим. Повторюсь: можете назвать продукт (не язык, а программу), где широко используется рефлексия и который используется более 10 лет? lpd>В Java фреймворках используется, не в курсе что ли? И софта на них может больше, чем на С++.
Да неужели? Вот, возьмём Eclipse. Допустим с его помощью я редактирую текстовый файл. Как и для чего используется Рефлексия в этом случае?
Здравствуйте, YuriV, Вы писали:
YV>Здравствуйте, Kluev, Вы писали:
YV>Правда что ли? Суждениями похож на любителя раста, те тоже рассуждают о том чего не знают.
YV>[ccode]
YV>class storage { YV>public: YV> class blob; YV>};
Так идея в том чтобы storage тоже имел "forward declaration" наряду с blob.
Это не идея, а непонимание. Полный тип в C++ это его имя и описание его структуры. А "forward declaration" объявляет лишь имя типа (incomplete type) структура которого сейчас неизвестна и поэтому получить доступ к структуре (storage::blob) incomplete type через его имя невозможно. Тут всё логично и никакой "дыры" в языке нет. Можно ввести в язык расширяемые классы, ну как namespace может расширяться в разных единицах трансляции новыми declaration/definition. Этакая альтернатива наследованию, но к чему это может привести прогнозировать сложно.
Здравствуйте, YuriV, Вы писали:
YV>Здравствуйте, Kluev, Вы писали:
K>>С вложенным классом Storage::Blob такой номер не пройдет т.к. в языке С++ нет механизма опережающих описаний.Это баг уровня языка который нужно исправлять. Как бы вы тут не распинались, что это и не нужно.
K>>
YV>Правда что ли? Суждениями похож на любителя раста, те тоже рассуждают о том чего не знают.
YV>Собирается gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), С++98,
YV>g++ main.cpp main_impl.cpp -o main
YV>Может это баг уровня твоего знания С++?
Сначала разберись, что здесь обсуждают, а потом уже лезь в разговор без хамства и перехода на личностей.
Здравствуйте, YuriV, Вы писали:
YV>Здравствуйте, Zhendos, Вы писали:
Z>>Так идея в том чтобы storage тоже имел "forward declaration" наряду с blob.
Z>>https://stackoverflow.com/questions/951234/forward-declaration-of-nested-types-classes-in-c
YV>Это не идея, а непонимание. Полный тип в C++ это его имя и описание его структуры. А "forward declaration" объявляет лишь имя типа (incomplete type) структура которого сейчас неизвестна и поэтому получить доступ к структуре (storage::blob) incomplete type через его имя невозможно. Тут всё логично и никакой "дыры" в языке нет. Можно ввести в язык расширяемые классы, ну как namespace может расширяться в разных единицах трансляции новыми declaration/definition. Этакая альтернатива наследованию, но к чему это может привести прогнозировать сложно.
Неверно. Вложенный тип не является частью типа, а находится в его пространстве имен.
Нет никаких проблем чтобы сделать опережающее описание следующим образом:
Здравствуйте, so5team, Вы писали:
S>А вообще речь шла о том, что кроме авторов STL есть разработчики, которые находят логичным использование беззнаковых чисел для размеров и индексов. Т.е. авторы STL вовсе не были "белыми воронами".
Конечно есть. Даже если заставлять С++ников прямо жрать говно, то мне кажется чуть ли не половина начнёт доказывать, что так и надо и что там есть полезные витамины.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, T4r4sB, Вы писали:
S>>>Но это не так. И авторы STL не единственные люди, которые считают, что размеры и индексы должны быть беззнаковыми.
TB>>Вообще-то они уже признали, что это была ошибка.
S>Если под "они" подразумеваются авторы STL, то где об этом можно прочитать?
S>А вообще речь шла о том, что кроме авторов STL есть разработчики, которые находят логичным использование беззнаковых чисел для размеров и индексов. Т.е. авторы STL вовсе не были "белыми воронами".
За этим "логичным" решением стоит целый лес граблей, ладно когда его не видит обычный разработчик, но когда "близорукость" у создателей стандарт пиши пропало.
Вот один из примеров. Допустим нужно перебрать все элементы кроме первого и последнего:
for (int i = 1; i < v.signed_size() - 1; i++)
{
v[i];
}
for (size_t i = 1; i < v.unsigned_size() - 1; i++)
{
v[i];
}
Со знаковым индексом пример всегда будет корректно работать, с беззнаковым на пустой коллекции ошибка времени выполнения.
Здравствуйте, T4r4sB, Вы писали:
TB>Конечно есть. Даже если заставлять С++ников прямо жрать говно, то мне кажется чуть ли не половина начнёт доказывать, что так и надо и что там есть полезные витамины.
Любопытно. В сообщении, на которое вы ответили, был вопрос о том, где можно прочитать про признание ошибки. Так же, без упреков в чью-то сторону, было сказано, что есть люди, который находят смысл в беззнаковых индексах и размерах.
Ничего конструктивного и полезного вы не сказали, но зачем-то завели речь про "жрать говно".
И если опуститься на ваш уровень и продолжить разговор про "говно", то окажется, что наезжает и хамит so5team.
Здравствуйте, Kluev, Вы писали:
S>>* пространства имен не решают ни одной проблемы, а взамен можно использовать префиксы;
K>Именно так господа. В с++ пространства имен не более чем синтаксический сахар без которого прекрасно можно жить и многие так и делают.
Здравствуйте, Kluev, Вы писали:
K>Неверно. Пространство имен класса очевидно присутствует в опережающем описании. Вот оно:
K>
K>classstorage;
K>
K>Поэтому нет никаких проблем с объявлением вложенного класса.
В общем, я просмотрел инфу по поводу forward nested class declaration и беру свои слова обратно. Я согласен с Kluev — все проблемы, которые якобы возникают от такого нововведения смехотворны. Возникающие ошибки (типа защищённого или приватного последующего определения вложенного класса или отсутствия одного из определений в доступных для компиляции единицах трансляции) описываются стандартными сообщениями компилятора/линкера. Вот здесь вердикт Trip Report: C++ Standards Meeting in Jacksonville, February 2016
Proposals for which further work is encouraged:
...
Forward declarations of nested classes. This would allow things like X::A* to appear in a header without requiring a definition for X to also appear in the header (forward-declarations of X and X::A will be sufficient). EWG found the use case compelling, because currently a lot of class definitions to appear in headers only because interfaces defined in the header use pointers or references to nested classes of the type. Several details still need to be worked out. (For example, what happens if a definition of X does not appear in any other translation unit (TU)? What happens if a definition of X appears in another TU, but does not define a nested class A? What happens if it does define a nested class A, but it’s private? The answer to some or all of these may have to be “ill-formed, no diagnostic required”, because diagnosing errors of this sort would require significant linker support.)
Но никто этим предложением не занимался, видимо все обходятся friend class'ами и данное предложение не толкают активно.
И добавлю относительно комитета, это ИМХО и оно никак не связано с вышеупомянутыми вложенными классами. Ниже по ветке я постил "другое" мнение о пути развития C++. Добавлю лишь, что у сегодняшнего комитета полностью отсутствует стратегическое целепологание, а точнее "недемократическая" компетентная группа способная принимать окончательные волевые стратегические решения о пути развития языка. Отсюда принятие фич ради фич и фич, которые интенсивнее педалируют без оглядки на развитие самого языка, на изменение подходов к программированию на этом языке, на современные требования к интеграции языка в инфраструктуру разработки.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Kluev, Вы писали:
R>А вот так будет работать как со знаковыми, так и с беззнаковыми:
R>
R> for (size_t i = 1; i + 1 < v.unsigned_size(); ++i)
R> {
R> v[i];
R> }
R>
R>Готов выслушать гневные обвинения в свой адрес
Дополнительные мысленные усилия потраченные совершенно впустую, как при написании, так и при чтении этого кода. Эдакая акробатика в инвалидной коляске.
Здравствуйте, Kluev, Вы писали:
K>Дополнительные мысленные усилия потраченные совершенно впустую, как при написании, так и при чтении этого кода. Эдакая акробатика в инвалидной коляске.
Какого-то такого ответа я и ожидал. Перенос слагаемого из одной части в другую — это сверхакробатика, конечно. Впрочем, как и любая другая попытка исправить ошибку в коде, которая так тебе дорога.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Kluev, Вы писали:
K>>Дополнительные мысленные усилия потраченные совершенно впустую, как при написании, так и при чтении этого кода. Эдакая акробатика в инвалидной коляске.
R>Какого-то такого ответа я и ожидал. Перенос слагаемого из одной части в другую — это сверхакробатика, конечно. Впрочем, как и любая другая попытка исправить ошибку в коде, которая так тебе дорога.
У нормальных людей от перемены мест слагаемых сумма не меняется.
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, boomer, Вы писали:
B>>Так оно и так только глобальное.
NB>есть две функции NB>
NB>namespace a { struct test {}; }
NB>void foo(T x, T y)
NB>{
NB> using namespace std::swap;
NB> swap(x, y);
NB>}
NB>foo(a::test{}, a::test{});
NB>namespace b { struct test {}; void swap(T, T); }
NB>void bar (T x, T y)
NB>{
NB> swap(x, y);
NB>}
NB>bar(b::test{}, b::test{});
NB>
NB>какие определения функции swap у тебя будут в глобальном пространстве имен, чтобы получить похожее поведение?
Ну получили вы подобное поведение. И что у вас на выходе? Лабиринт из костылей. С введением семантики перемещения такие пируэты вокруг функции свап болше не нужны. Но видимо Ватсон без трубки уже не может.
Здравствуйте, night beast, Вы писали:
NB>Здравствуйте, Kluev, Вы писали:
K>>Ну получили вы подобное поведение. И что у вас на выходе? Лабиринт из костылей. С введением семантики перемещения такие пируэты вокруг функции свап болше не нужны. Но видимо Ватсон без трубки уже не может.
NB>если кое-кто не в состоянии понять, что это была демонстрация возможностей, то я ничем помочь не могу
Демонстрация возможностей чего? Костыле-ориентированного программирования? Спасибо не нужно.
Здравствуйте, Kluev, Вы писали:
K>"Всегда будет" — это громкие, но пустые заявления. Вот к примеру простой жизненный пример: итерация пар соседних элементов в массиве для вычисления длинны полилинии
K>
K> double len = 0;
K> for (int i = 0; i < points.size() - 1; i++)
K> len += distance(point[i], point[i + 1]);
K> return len;
K>
K>Один универсальный цикл на все случаи жизни. Никакие дополнительные ветки не нужны. В std::С++ такое естественно работать не будет, std-программист либо наступит на грабли, либо будет вынужден погрузиться в микро-менеджмент и "перебрасывать слагаемые"
А теперь представим, что в процессе сопровождения и оптимизации у вас points из вектора превратился в простой список или список чанков. И у вас больше нет индекса, зато есть итераторы, которые позволяют вам итерироваться по новому контейнеру последовательно.
Ведь ваш цикл останется именно таким на все случаи жизни, не правда ли?
Ну или давайте посмотрим на знаковые индексы/размерности с другой стороны. Насколько они удобны не для последовательных итераций, а для произвольного доступа. Вот у нас есть вектор v размера N и мы по сложной формуле вычисляем позицию i в этом векторе. А перед обращением к v(i) нам нужно убедится, что i валидный. Что нам потребуется?
Потребуется написать два условия в проверке:
if(i >= 0 && i < N)
вместо всего одной для случая беззнаковых размеров и индексов.
Так вот, поскольку вы наверняка не поймете к чему я привожу эти примеры, мораль сей басни такова: ваш "малолетний дебилизм" состоит в том, что вы признаете единственно правильной только свою точку зрения. И в упор отказываетесь принимать тот факт, что ни у знаковых размерностей, ни у беззнаковых нет абсолютных преимуществ во всех сценариях использования. А раз так, то какой бы выбор не был сделан, всегда будут сценарии, когда сделанный выбор ведет либо к проблемам, либо к дополнительным накладным расходам.
Понимай вы это, вы бы не позволили себе высказывания в стиле юношеского максимализма, вроде: "Человек который имеет другую точку зрения, конечно имеет на нее полное право, но по сути является садомазохистом и не подходит для принятия общественно значимых решений по моральным качествам." Именно такой юношеский максимализм в ваших высказываниях и позволяет классифицировать вас как "малолетнего дебила".
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>"Всегда будет" — это громкие, но пустые заявления. Вот к примеру простой жизненный пример: итерация пар соседних элементов в массиве для вычисления длинны полилинии
K>>
K>> double len = 0;
K>> for (int i = 0; i < points.size() - 1; i++)
K>> len += distance(point[i], point[i + 1]);
K>> return len;
K>>
K>>Один универсальный цикл на все случаи жизни. Никакие дополнительные ветки не нужны. В std::С++ такое естественно работать не будет, std-программист либо наступит на грабли, либо будет вынужден погрузиться в микро-менеджмент и "перебрасывать слагаемые"
S>А теперь представим, что в процессе сопровождения и оптимизации у вас points из вектора превратился в простой список или список чанков. И у вас больше нет индекса, зато есть итераторы, которые позволяют вам итерироваться по новому контейнеру последовательно.
А давайте представим, что земля завтра налетит на небесную ось?
У классов на основе списков и на основе массивов разные сценарии использования, и если требуется то такие в программе живут параллельно, а не переделываются из одного в другой.
S>Ведь ваш цикл останется именно таким на все случаи жизни, не правда ли?
S>Ну или давайте посмотрим на знаковые индексы/размерности с другой стороны. Насколько они удобны не для последовательных итераций, а для произвольного доступа. Вот у нас есть вектор v размера N и мы по сложной формуле вычисляем позицию i в этом векторе. А перед обращением к v(i) нам нужно убедится, что i валидный. Что нам потребуется?
S>Потребуется написать два условия в проверке: S>
S>if(i >= 0 && i < N)
S>
S>вместо всего одной для случая беззнаковых размеров и индексов.
Это вам потребуется. А мне потребуется написать
if (vec.valid_index(i))
Я использую свои классы с рациональным набором операций
S>Так вот, поскольку вы наверняка не поймете к чему я привожу эти примеры,
Если вы себя официально позиционируете умнее своего собеседника, то вам надо видеть хотя-бы дальше своего носа. Но в вашем наивном примере, в якобы эффективном переходе от двух сравнений в if(i >= 0 && i < N) к одному в беззнак.арифметике, вы не видите леса за своим носом. Если вы "вычисляете" индекс в беззнаковой арифметике, то чтобы избежать переполнения ваши проверки просто переедут из кода обращения к массиву, в код вычисления индекса. Причем их число будет пропорционально размеру кода. В знаковой арифметике вы откупаетесь одним простым и эффективным if(i >= 0 && i < N)
S> мораль сей басни такова: ваш "малолетний дебилизм" состоит в том, что вы признаете единственно правильной только свою точку зрения. И в упор отказываетесь принимать тот факт, что ни у знаковых размерностей, ни у беззнаковых нет абсолютных преимуществ во всех сценариях использования. А раз так, то какой бы выбор не был сделан, всегда будут сценарии, когда сделанный выбор ведет либо к проблемам, либо к дополнительным накладным расходам.
Вы так говорите как будто каждый раз в коде делаете осознанный выбор в пользу знак. или беззнак. индексов. На самом деле кушаете то, что подают в стл. Мой осознанный выбор знаковая арифметика. Согласитесь что в такой ситуации ваши нравоучения и напыщенное сектанство не уместны. Вы — человек действующий шаблонно по указивке комитета, пытаетесь поучать человека действующего осознанно. Это просто смешно.
S>Понимай вы это, вы бы не позволили себе высказывания в стиле юношеского максимализма, вроде: "Человек который имеет другую точку зрения, конечно имеет на нее полное право, но по сути является садомазохистом и не подходит для принятия общественно значимых решений по моральным качествам." Именно такой юношеский максимализм в ваших высказываниях и позволяет классифицировать вас как "малолетнего дебила".
Здравствуйте, Kluev, Вы писали:
S>>Требования к софту меняются. Профилирование заставляет менять структуры данных в программе. И т.д., и т.п.
K>Не припомню случая когда приходилось бы менять вектор на список и наоборот. Слишком разные сценарии использования. А проектировать софт с учетом возможного столкновения с небесной осью я смысла не вижу.
Т.е. если вы не видели, значит этого нет. Понятно.
А такие случаи бывают. Более того, для каких-то сценариев приходится менять тип контейнера прямо в run-time, скажем, с vector на map или set.
А теперь возвращается к вашему "циклу на все случаи жизни". Он таковым не является. А вот если бы вы написали его на итераторах, то он бы при переходе от vector к list или deque или даже к set не поменялся бы. При этом вам было бы фиолетово, что скрывается за итератором -- знаковые индексы или беззнаковые.
K>>>В знаковой арифметике вы откупаетесь одним простым и эффективным if(i >= 0 && i < N)
S>>Т.е. в вашей вселенной if(i>=0 && i<N) прощее и эффективнее if(i < N)? O_o.
K>Имею смелость утверждать.
Т.е. аргументация "Kluev сказал"? Ну тогда сразу в /dev/null вместе с утверждениями "Человек который имеет другую точку зрения, конечно имеет на нее полное право, но по сути является садомазохистом и не подходит для принятия общественно значимых решений по моральным качествам."
K>Т.к. реальном мире любая операция минус в беззнаковой арифметике небезопасна и потребует проверки, любая смешанная арифметика небезопасна и потребует проверки. Написание проверок требует дополнительных мысленных усилий и ухудшает читаемость и качество кода.
Ох ё, детский сад, младшая ясельная группа. А знаковые у вас никогда не переполнялись? Или может вы думаете, что переполнение знаковых -- это ничего страшного, и даже не UB?
K>Отдельно взятый оператор if(i < N) будет эффективней отдельно взятого if(i>=0 && i<N) вот только за ним стоит такой лес граблей, ненужных проверок и ненужных усилий которые сводят на нет всю его мнимую эффективность.
Отучаемся говорить за всех (c).
K>Я не навязываю, а утверждаю очевидные вещи,
Повторюсь: поэтому-то вы "малолетний дебил" (с), который считает, что его инфантильные желания должны быть превыше всего, а его мнение безусловно является самым правильным.
K>Правильность моего мнения доказывает большинство языков программирования на нашей планете.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev
K>>С++ такие пируэты не поддерживает
K>>например при смене контейнера с list на vector итератор может стать невалидным (при вставке элемента в теле цикла). И в если случае с индексами вы бы получили ошибку компиляции и смогли бы провести ревизию кода, то с итераторами вы получите ошибку времени выполнения со всеми вытекающими последствиями. Т.е ваши методы гладки только на бумаге, а в реальной жизни гладкостью там и не пахнет. Собственно вся stl и есть бумажная концепция, малопригодная для программирования, для тех кто слаще морковки ничего в жизни не видел.
K>>Знаковые на пустом месте не переполняются.
K>>Ну а руст это очередной мертворожденный язык. Т.к время каркозябро-ориентированных языков требующих постоянного микроменеджемнта уже прошло.
S>Простите, но это уже не "малолетний дебилизм", это чистой воды идиотия.
Вам пишут очевидные вещи, вы называете их идиотией и сопровождаете оскорблениями. Вы адекватный вообще? Наверное стоит прекратить с вами общение.
Здравствуйте, Kluev, Вы писали:
K>Имею смелость утверждать. Т.к. реальном мире любая операция минус в беззнаковой арифметике небезопасна и потребует проверки,
Вы так пишите, как будто в знаковой проверка не нужна. А это не так.
K> double len = 0;
K> for (int i = 0; i < points.size() - 1; i++)
K> len += distance(point[i], point[i + 1]);
K> return len;
K>
K>Один универсальный цикл на все случаи жизни. Никакие дополнительные ветки не нужны. В std::С++ такое естественно работать не будет, std-программист либо наступит на грабли, либо будет вынужден погрузиться в микро-менеджмент и "перебрасывать слагаемые"
Здравствуйте, Nuzhny, Вы писали:
_>>Что же касается древних итераций по индексу в стиле C... Ну как бы иногда и такое бывает надо (личное мне оно особенно часто в графике встречалось и в матрицах, причём там уже актуальна оптимизация под SIMD и всё такое), но у меня такое ощущение, что некоторые программисты ставят их просто везде от незнания и неумения.
N>1. А как же одновременная итерация по нескольким массивам? У меня есть такой код, который только на индексах выглядит нормально. N>2. Случай итерации по модулю индекса. При рисовании замкнутых фигур или циклическому буферу. Тут есть что-то лучше индекса? N>3. Иногда индекс сам по себе несёт семантику, а не просто указывает на позицию элемента в контейнере.
Так я же вроде ясно написал, что иногда такое нужное (и мне в том числе, даже примеры привёл). Но думаю что вполне очевидно, что эти применения являются явным меньшинством по отношению к общему числу применений контейнеров в программе.
Здравствуйте, Kluev, Вы писали:
K>>>В обоих случаях переполнение приведет к ошибочному ходу выполнения программы. BFE>>Нет, конечно. На переполнение беззнаковых можно закладываться, а вот на переполнение знаковых — нет.
K>С переполнением беззнаковых сложнее работать, т.к. при переполнении у вас будет валидный индекс 0
Вот именно, что точно известно, что будет в отличии от знаковых целых.
K>а со знаковыми вы уйдете в отрицательную область невалидных индексов.
Не-а. При переполнении знакового целого вы уйдёте в область неопределённого поведения:
Note: Unsigned arithmetic does not overflow. Overflow for
signed arithmetic yields undefined behavior (7.1). —end note
7.1/4
If during the evaluation of an expression, the result is not mathematically defined or not in the range of
representable values for its type, the behavior is undefined.
K>>>Но случаев когда переполнение возможно в беззнаковой арифметике однозначно больше. BFE>>Конечно случаев больше и поэтому с беззнаковыми переменными программы лучше отлажены, так как выявление ошибки происходит практически сразу, а не через 2147483647 операций. K>а через 4294967296 операций с беззнаковыми что происходит?
Будет 0 (если uint32_t) и с переменной можно продолжать работать.
Ну и могли бы вы указать на оные замены? А то может речь идет о вещах типа small_vector и fixed_string?
K>Какая трагедия)))
Да. Как минимум это означает, что все ваши потуги можно смело и сразу отправлять в /dev/null.
S>>Для идиотов специально: там дело не в индексах, индексы никак не препятствуют сохранению ссылок на содержимое контейнера. И это глобальная проблема C++, решение для которой сейчас проходит проверку временем в Rust-е.
K>Мы сейчас обсуждаем С++ и его проблемы.
Для идиотов специально: там дело не в индексах, индексы никак не препятствуют сохранению ссылок на содержимое контейнера. И это глобальная проблема C++.
Так что от обсуждения проблем C++ мы никуда и не уходили, даже не смотря на то вы увидели в тексте слово Rust.
K>>>Вам все равно придется использовать индекс элемента, а т.к. в std он беззнаковый еще и заворачивать его в std::optional K>>>Вот так с кривым stl вы автоматически получаете кривизну на пустом месте.
S>>Вы правда не видите других альтернатив std::optional?
K>Альтернатив множество вплоть до вызова use_item прямо в теле цикла, разделение циклов на два и т.п. Я не телепат чтобы угадывать какую именно альтернативы вы выбрали.
Вот даже вы видите более одной альтернативы, но при этом почему-то в качестве _моего_ решения описываете одно из самых неэффективных, с использованием std::optional. Что наводит на мысль, что вы за меня выдумываете какие-то тезисы, а потом их же старательно и опровергаете.
K>Не ответил потому что посчитал их не существенными. Баг языка был показан однозначно. А на демагогию у меня времени нет.
Т.е. вы не посчитали существенной информацию, которую у вас просил ваш собеседник? Ну что же, значит с диагнозом нет ошибки.
И если у вас нет времени на демагогию, то почему вы столько дней здесь ей занимаетесь?
S>>Это не использование Storage::Blob. У вас здесь идиома opaque pointer. А в ней этот самый opaque pointer может быть чем угодно. И для opaque pointer вовсе не обязательно показывать пользователю ни класс Storage, ни класс Blob. Можно хоть void* здесь применять, хоть типизированные обертки вокруг void*.
K>Прямо у вас под носом как обычно. И в void foo(Storage::Blob *blob) происходит не идиома, о самое обыкновенное Pointer declaration
ППц, вы хоть бы матчасть подучили. Хотя бы на уровне спорных формулировок из Wikipedia: https://en.wikipedia.org/wiki/Opaque_pointer
S>>Т.е. вы признаете, что делаете резкие оценки в адрес того, чего не знаете?
K>Знаю достаточно чтобы не использовать. Запаха и вида вполне достаточно.
То, что вы не используете STL, наверное, даже хорошо. Проблема в другом: если вы не знаете предмета разговора, то ни ваше мнение, ни ваши оценки ничего не стоят. Но, будучи "малолетним дебилом" вы старательно хотите донести до всех свое "веское мнение" по теме, в которой не разбираетесь.
Здравствуйте, Kluev, Вы писали:
K>программист может сам себе гарантировать, в платформозависимом решении. это вполне оправдано. а если вы думаете что ваши программы будут выполнятся вечно на всех новых платформах и новом железе, то я вас расстрою. еще при нашей жизни от них и эха не останется.
Компилятор имеет полное право вырезать к чертям твой код, который приводит к UB (а переполнение знакового целого это UB). Так как никакое поведение не гарантировано, можно выбрать любое!
S>А вообще речь шла о том, что кроме авторов STL есть разработчики, которые находят логичным использование беззнаковых чисел для размеров и индексов. Т.е. авторы STL вовсе не были "белыми воронами".
а кто-то находит логичным иметь возможность написать assert(ix >= 0)
вообще там кмк проблема не в переполнении а в том, что у тебя в приложении зачастую происходит сравнение знаковых и беззнаковых, и вот такой код как раз сложнее отлаживать и поддерживать, намного лучше когда все знаковое, никаких тебе лишних приведений типов и проверок на narrowing и тд
Здравствуйте, RedApe, Вы писали:
RA>Здравствуйте, Шахтер, Вы писали:
Ш>>Вылечить можно так. Хакаем заголовок <compare>.
RA>Браво. Жаль, что не все программисты пользуются такими методами как ты.
Против лома нет приёма.
RA>Или можно так RA>
RA> std::strong_ordering cmp = .... ;
RA> if( cmp != 0 ) // ok
RA> {
RA> }
RA> else
RA> {
RA> }
RA> if (cmp < 0) { // ok
RA> } else if (cmp > 0) { // ok
RA> } else { // ok
RA> }
RA>
Здравствуйте, smeeld, Вы писали:
S>>Пользователям Envoy это расскажите, к примеру. А то они так страдают от того, что не выбрали многократно помянутый вами Apache TrafficServer, что прямо спать не могут. S>Что это? Кто это? А, очередной хеллоуворлд с гатхаба. Неинтересно (уходит писать плагин для nginx)
LOL.
Envoy используется для коммутации трафика между сервисами, во многих компаниях из Top500.
Здравствуйте, so5team, Вы писали:
S>Envoy же является примером производительного решения, которое написано как раз на современном C++.
Теперь, ясно. Ну,я в этом и не сомневался.
S>Ретроградов, типа вас с smeeld, это вряд ли в чем-то убедит. Но может быть кого-то заставит перестать брать слова smeeld на веру.
Я вообще-то совсем не ретроград и я вижу со стороны как код преображается, и в целом, наверное в лучшую сторону. Не могу сказать, что прям вах-вах, но плохого не вижу.
То, что я выразил согласие выше — означает только лишь согласие, что и старые методы отлично работают без новых перделок. Но, применения чистого C в прикладных задачах — я лично — не вижу. Разумеется, он вполне подходит для ядра, ведь все структуры данных один хер самописные, а шаблонная магия там не упала, ведь обеспечить ABI — надо, чего в прикладухе нет, да и в среднем по палате у C++-ников (как и у других) есть крайне приблизительное понимание этого вопроса.
Здравствуйте, smeeld, Вы писали:
S>Это говорит прежде всего о том, что вы не учитываете политический момент. А именно он и определяет то, каким компилятором должен собираться линукс.
Тут крыть нечем.
Здравствуйте, PM, Вы писали:
PM>И судя по частоте релизов, никто там не хочет сильно трогать ту кучу субстанции. Код != продукт.
Для такого монстра, у них очень хорошо в релизами. К тому же, DB ориентирован на кровавый тырпрайз, а там очень не любят частые релизы, раз в два-три года-это то, что нужно. Чаще-гемор.
Здравствуйте, Mystic Artifact, Вы писали:
C>>Envoy используется для коммутации трафика между сервисами, во многих компаниях из Top500. MA> Топ500 использует еще 100500 всякой хрени в самых разных местах. Если им это надо — это не значит, что остальной части населения, которой >99.9% нужно вообще об этом знать. Какие выводы можно сделать из того что они используют? Да никаких.
99.99% населения Envoy и не нужен, так как у них нет сети сервисов. А там где Envoy нужен — таки nginx даже близко не поможет. И таки да, он написан очень правильно.
Здравствуйте, smeeld, Вы писали:
S>И как же в крупных проектах на Си и Си c классами обходятся без этих понтов и заклинаний aka std::move, std::swap и прочих trivially_constructable?
пишут нечитаемое и неподдерживаемое говно с UB, ломающееся при переходе на новую версию компилятора
Здравствуйте, smeeld, Вы писали:
S>На серверах и железках доминирует чистый Cи, и будет, пока линуксы и прочие оракелы на Cи написаны, а замены им не видно. А в тырпрайзе C++ и не было никогда, там java балом правит.
Здравствуйте, lpd, Вы писали:
lpd>Ядро линукса (кроме некоторых участков вроде отдельных драйверов или sunrpc, например) вполне читабельно. Я не претендую, что все детали там знаю. Но при том огромном количестве фич которые оно содержит, обычно можно разобраться и найти концы, почему что-то не работает. Я бы впрочем и его меньше оптимизировал, начиная с тех же лишних на мой взгляд likely/unlikely во многих if. Но это лучше мув-семантики на каждом шагу лишь бы ее использовать.
Не, так не пойдет. Дайте, пожалуйста, ссылку на конкретный фрагмент кода.
Здравствуйте, Шахтер, Вы писали:
Ш>Комитет по стандартизации пора расстрелять. Такое ощущение, что эти дебилы никогда не писали софт сложнее hello world.
Ш>
Ш>Кстати, обратите внимание, какие замечательные короткие имена нам предлагают использовать для констант. На пол-экрана. А чо такова, мониторы-то теперь широкие?
Ш>Вылечить можно так. Хакаем заголовок <compare>.
Комиссар, просвятите пожалуйста старого дореволюционного профессора. То, что имена в стд длинные итп — это да,
а вот не хакая <compare> есть какое-нить решение?
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, lpd, Вы писали:
S>Ну вот сходу типичное для чисто Сишного кода: как понять, где в коде этой функции можно сразу делать retun r;, а где нужно r = ...; goto out, а где r = ...; goto cancel_injection;? Посредством каких-то тайных знаний, штудирования документации, штудирования комментариев или внимательного разбирательства с кодом этой функции?
Это освобождение ресурсов, достаточно очевидное как всегда в таких случаях. В строке 8321 в guest инжектится прерывание, сводится к
inject_pending_event:
else if (vcpu->arch.interrupt.injected)
kvm_x86_ops->set_irq(vcpu);
Если после этого до переключения исполнения в guest произошла ошибка или изменено решение о переходе в guest, естественно нужно это прерывание сбросить, поэтому goto cancel_injection. Соответственно до строки 8321 с инжектом прерывания, правилен goto out. По-моему это вполне очевидно.
А ты бы использовал исключения или RAII? Наверное можно. С освобождением ресурсов кстати реально бывает много багов в линуксе, но обычно менее очевидных, чем goto не на ту метку выхода. Я например, очень редко забываю что-то освободить в простых случаях, скорее мешают логические ошибки при выходе из середины функции.
Кроме того, с goto код очевиден. А вот в С++ обычно код менее явный и нужно вникать где же ресурс на самом деле освободится. Впрочем можно было это и с использованием С++ это написать, были бы и преимущества такого подхода. Но если в ядро еще добавить мув-семантику и сложные шаблоны, то в нем точно очень мало кто сможет разобраться, т.к. там и без них сложностей хватает.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, lpd, Вы писали:
lpd>Это освобождение ресурсов,
Это очевидно.
lpd>достаточно очевидное как всегда в таких случаях.
Аж два раза. Вы даже суть вопроса не поняли, а уже объяснять побежали.
Вопрос был в том, как не вычитывая досконально весь код этой портянки понять, что вот здесь при добавлении нового фрагмента еще можно делать goto out, а вот здесь уже только goto cancel_injection.
Очевидно, что никак.
lpd>А ты бы использовал исключения или RAII?
Не пытайтесь думать за других.
Исключения здесь не нужны. А вот RAII и какой-то вариант scope guard-а помог бы.
lpd>Кроме того, с goto код очевиден.
Здравствуйте, so5team, Вы писали:
S>Вопрос был в том, как не вычитывая досконально весь код этой портянки понять, что вот здесь при добавлении нового фрагмента еще можно делать goto out, а вот здесь уже только goto cancel_injection.
S>Очевидно, что никак.
Модифицировать функцию, не читая ее код, и не понимая что она делает — это действительно высший пилотаж, мне такое не под силу.
Ну и в конкретно этом примере RAII помог бы слабо, т.к. это не освобождение ресурса, а вызов специальных функций, и в лоб по С++ному ничего тут не сделать.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, lpd, Вы писали:
S>>Не, так не пойдет. Дайте, пожалуйста, ссылку на конкретный фрагмент кода.
lpd>Ну вот тебе большая функция-кошмар плюсовика: kvm
Почему, кстати, все в if'ах, там else if'ы имхо нужны, я так понимаю, там всё же не флаги проверяются, а типа enum'ы
Здравствуйте, lpd, Вы писали:
S>>И, что характерно, штудируют не все, и не всегда тщательно.
lpd>Тут штудировать нечего, освобождение ресурсов и другие подобные операции вполне очевидны.
Они так очевидны, что вы даже не поняли, о чем я вас спрашивал.
Полагаю, сишники считают такие вещи очевидными потому, что подолгу сидят над одной и той же кодовой базой. А по другому и не получается. В смысле быстро с сишным кодом не разберешься. Потому успевают вызубрить код, по котором приходится ползать со скоростью мухи.
S>>Это говорит лишь о том, что вы слабо себе представляете, что в современном C++ можно делать с помощью RAII (да и в старом, только там несколько многословнее все).
lpd>Создать объект-обертку над функцией? Спасибо, у меня других проблем хватает, чем городить такие конструкции на ровном месте, и усложнять код.
Вы бы взяли на себя труд и ознакомились бы с предметом разговора. А то выступаете в духе "Пастернака не читал, но осуждаю".
lpd>Я больше про мув-семантику, шаблоны и умные указатели писал, впрочем по-моему не раз уж спорил здесь, в том числе с вашими.
И где в приведенных вами примерах можно увидеть адекватную замену всему вышеперечисленному, но в рамках чистого Си?
Уж не думаете ли вы, что если на C++ придется написать подобный линейный код, как во фрагменте из kvm, то там на ровном месте наплодят еще один boost.xpressive?
lpd>Я привел пример кода который я считаю приятно читать и писать.
Не видно ни того, ни другого. Особенно письмо требует чрезвычайной внимательности и осторожности + глубокого понимания всех деталей и исторических наслоений.
Пример этого уже был приведен выше.
lpd>но надеюсь программисты в массе все же поймут что современный С++ это только для фанатиков фич языка, пытающихся все проблемы решить новым синтаксисом, а не для реального кода, в котором и без того сложностей хватает.
Тут бы очень не помешал пример такого C++ного кода-страшилки с альтернативной реализацией на чистом Си. Чтобы сразу стало понятно, что те же самые задачи можно решать проще, компактнее, дешевле и с меньшим количеством ошибок.
Здравствуйте, lpd, Вы писали:
lpd>Бог с ним с RAII, если он так нравится, это вопрос стиля. Я больше про мув-семантику, шаблоны и умные указатели писал, впрочем по-моему не раз уж спорил здесь, в том числе с вашими.
не буду спорить про шаблоны, с ними и правда можно написать так, что потом сам черт ногу сломит (а можно и наоборот), но что не так с мув-семантикой и умными указателями?
мув-семантика, помимо возможности оптимизации некоторых вещей позволяет выразить в коде явным образом владение ресурсом, следовательно она упрощает код
с умными указателями та же история, если не абьюзить shared_ptr, то в коде становится явно видно что у одного объекта единственный владелец, а у другого нет
Здравствуйте, chaotic-kotik, Вы писали:
CK>мув-семантика, помимо возможности оптимизации некоторых вещей позволяет выразить в коде явным образом владение ресурсом, следовательно она упрощает код
Оптимизацию я не считаю за плюс, т.к. в тех редких случаях когда копирование памяти занимает значительное время в критическом участке, проще скопировать указатель вручную(что мув семантика и делает по сути).
В плане использования для владения ресурсом, то если вы получите преимущества, то ок. Для чего только, все ради хэндлов и файлов? Лично мне такое не нужно было никогда в коде, особенно чтобы это оправдывало новый тип rvalue-reference и все сложности сопутствующего синтаксиса.
И особенно когда некоторые начинают делать мув всех переменных в коде каких можно, это точно абсурд.
CK>с умными указателями та же история, если не абьюзить shared_ptr, то в коде становится явно видно что у одного объекта единственный владелец, а у другого нет
Умные указатели полезная вещь, я и сам их как-то реализовывал. Но это в некоторых случаях, когда владение объектами без него участь сложно; и не нужно делать все указатели умными, как рекомендуют фанатики С++. Вообще, умные указатели не снимают головной боли с круговыми ссылками, поэтому если уж делать нормально, то сборка мусора удобнее, отключаемая конечно.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, lpd, Вы писали:
lpd>Но это лучше мув-семантики на каждом шагу лишь бы ее использовать.
Всегда раньше лоллировал с таких аргументов. Если речь идет о С++ то конечно пренепременно должен быть МАКСИМАЛЬНЫЙ abuse и overuse ВСЕХ возможностей языка ( даже не обсуждается ). Но если речь о C, то конечно по умолчанию всегда идеальный, кристальной чистый код, не иначе как самим господом богом написаный. И конечно ж не может и речи идти о лишнем или нецелесообраном использованием goto, арифметики указателей, void*, привидиния всего ко всему, ООП головного мозга и макросов. Все и всегда только по делу.
Здравствуйте, lpd, Вы писали:
lpd>Здравствуйте, chaotic-kotik, Вы писали:
CK>>мув-семантика, помимо возможности оптимизации некоторых вещей позволяет выразить в коде явным образом владение ресурсом, следовательно она упрощает код
lpd>Оптимизацию я не считаю за плюс, т.к. в тех редких случаях когда копирование памяти занимает значительное время в критическом участке, проще скопировать указатель вручную(что мув семантика и делает по сути).
скопировать указатель намного проще чем скопировать и проследить, чтобы новый владелец его удалил
помимо этого, не все живет в куче, а добавлять лишний indirection не всегда вариант
еще move позволяет упростить некоторые вещи, например сложную синхронизацию можно сделать с использованием unique_lock + move
lpd>В плане использования для владения ресурсом, то если вы получите преимущества, то ок. Для чего только, все ради хэндлов и файлов? Лично мне такое не нужно было никогда в коде, особенно чтобы это оправдывало новый тип rvalue-reference и все сложности сопутствующего синтаксиса.
но если он уже есть, то почему бы и нет? с unique_ptr работа со всякими хэндлами и файлами реализуется очень тривиально, почему бы не пользоваться? накладных расходов 0, ничего не течет, все гарантированно удаляется и освобождается
lpd>И особенно когда некоторые начинают делать мув всех переменных в коде каких можно, это точно абсурд.
явный move редко когда бывает нужен, если по хорошему
CK>>с умными указателями та же история, если не абьюзить shared_ptr, то в коде становится явно видно что у одного объекта единственный владелец, а у другого нет
lpd>Умные указатели полезная вещь, я и сам их как-то реализовывал. Но это в некоторых случаях, когда владение объектами без него участь сложно; и не нужно делать все указатели умными, как рекомендуют фанатики С++. Вообще, умные указатели не снимают головной боли с круговыми ссылками, поэтому если уж делать нормально, то сборка мусора удобнее, отключаемая конечно.
сборка мусора може и удобнее но тормознее, цикличесские ссылки дебажатся довольно тривиально, unique_ptr циклических ссылок не создает в принципе, без того же unique_ptr крайне геморно освобождать память при наличии исключений, тривиальный пример:
x = new X();
y = new Y(); //< throws exception
против
x = std::make_unique<X>();
y = std::make_unique<Y>();
Здравствуйте, chaotic-kotik, Вы писали:
CK>Здравствуйте, lpd, Вы писали:
CK>но если он уже есть, то почему бы и нет? с unique_ptr работа со всякими хэндлами и файлами реализуется очень тривиально, почему бы не пользоваться? накладных расходов 0, ничего не течет, все гарантированно удаляется и освобождается CK>еще move позволяет упростить некоторые вещи, например сложную синхронизацию можно сделать с использованием unique_lock + move
Во-первых, мув-семантика — это не тривиально. Это новый тип с новыми правилами работы с ним, без опыта с которыми будут сложности.
Во-вторых, RAII это не серебрянная пуля. Полно случаев когда он не описывает сложное владение объектом.
CK>>>с умными указателями та же история, если не абьюзить shared_ptr, то в коде становится явно видно что у одного объекта единственный владелец, а у другого нет
Может это и ясно, но синтаксис у умных указателей очень громоздкий. И тут начнутся всякие auto, с которыми уже вообще ничего в коде не видно.
CK>сборка мусора може и удобнее но тормознее, цикличесские ссылки дебажатся довольно тривиально
Не уверен что так тривиально они дебажатся всегда.
CK>, unique_ptr циклических ссылок не создает в принципе, без того же unique_ptr крайне геморно освобождать память при наличии исключений, тривиальный пример:
Я бы предпочел вручную освобождение прописать, хотя если нравится RAII то могу понять.
CK> сборка мусора може и удобнее но тормознее
Вроде как никто не мешает тормозящие массовые объекты и самому при сборке мусора удалять(тут я не специалист). Если сборка мусора тормозит, ее можно отключить и перейти на ручную работу с памятью или умные указатели.
Вообщем, если очень нравится RAII, то я могу понять твои аргументы.
Но лично я подписывался под старым С++03. И появись С++17 одновременно с ним, под другим названием(ComplexC, например), я бы писал на С++03, как наверняка и многие другие.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
lpd>Вообщем, если очень нравится RAII, то я могу понять твои аргументы. lpd>Но лично я подписывался под старым С++03. И появись С++17 одновременно с ним, под другим названием(ComplexC, например), я бы писал на С++03, как наверняка и многие другие.
Так пиши на С++03, кто тебе мешает?
Я так и делаю, за исключением некоторых новых мелочей типа лямбд и тп.
S>>Полагаю, разбираться в чужих макросах сильно проще, чем в чужих шаблонах.
lpd>Макросы — это всего лишь препроцессор, поэтому они проще шаблонов, как ни крути.
Здравствуйте, Шахтер, Вы писали:
Ш>Комитет по стандартизации пора расстрелять. Такое ощущение, что эти дебилы никогда не писали софт сложнее hello world.
Ш>
Здравствуйте, lpd, Вы писали:
lpd>Ты наверное понимаешь, что skb — указатель, и (skb+1) в данном случае смысла не имеет. lpd>Будет просто skb_rbtree_walk_from(skb_rb_next(skb)). Так что непонятно в чем твоя претензия в данном случае.
А вы, наверное, не понимаете, что вместо (skb+1) может быть что угодно. Скажем (skb++). И тогда макрос развернется во что-то вроде
for (; skb++ != NULL; \
skb++ = skb_rb_next(skb++))
lpd>Макросы — это всего лишь препроцессор, поэтому они проще шаблонов, как ни крути.
Сами по себе, возможно. А вот то, что на макросах пытаются строить...
lpd>Также в С полегче предсказать какой бинарный код получится и разбираться в ассемблерных дампах, что в ядре является плюсом.
Т.е. высказанные вами предпочтения должны приниматься во внимание только при разработке ядра Linux-а, правильно?
Здравствуйте, lpd, Вы писали:
lpd>Во-первых, мув-семантика — это не тривиально. Это новый тип с новыми правилами работы с ним, без опыта с которыми будут сложности.
с чем угодно будут проблемы, если не уметь этим пользоваться, если ты не хочешь пользоваться мув семантикой, никто тебя не заставляет это делать, не добавишь ее поддержку в свой класс и он будет просто копироваться, тоже мне проблема
lpd>Во-вторых, RAII это не серебрянная пуля. Полно случаев когда он не описывает сложное владение объектом.
это какие же?
lpd>Может это и ясно, но синтаксис у умных указателей очень громоздкий. И тут начнутся всякие auto, с которыми уже вообще ничего в коде не видно.
Это чем же он громоздкий? Сишные st1->st2.fld3->st4 это значит не громоздко совсем, да?
CK>>сборка мусора може и удобнее но тормознее, цикличесские ссылки дебажатся довольно тривиально lpd>Не уверен что так тривиально они дебажатся всегда.
с помощью ASan довольно тривиально, но вообще это не приходится делать, если правильно проектировать архитектуру, то бишь делать так, чтобы граф зависимостей объектов был ацикличным и направленным (это также неплохо помогает от дедлоков), то что сишечка позволяет иметь кучу циклических ссылок между объектами вовсе не значит что их нужно обязательно создавать и что это есть хорошо
lpd>Я бы предпочел вручную освобождение прописать, хотя если нравится RAII то могу понять.
тут дело не в RAII, а в том, что вручную придется прописывать в нескольких местах, потому что исключения
Явный new/delete или malloc/free в проекте на С++ это чаще всего code smell, нет реально ни одной причины для того, чтобы выделять и освобождать память или создавать и удалять объекты таким способом. Ты так предпочитаешь делать, ок, но для всех остальных в этом нет никакой логики, это просто код с душком. Автор кода просто зачем-то сделал что-то странное, нужно повнимательнее посмотреть на ревью.
lpd>Вроде как никто не мешает тормозящие массовые объекты и самому при сборке мусора удалять(тут я не специалист). Если сборка мусора тормозит, ее можно отключить и перейти на ручную работу с памятью или умные указатели.
там не удаление объектов тормозит, а поиск объектов, которые никто не использует и которые можно удалить
Здравствуйте, chaotic-kotik, Вы писали:
CK>Здравствуйте, lpd, Вы писали:
lpd>>Во-вторых, RAII это не серебрянная пуля. Полно случаев когда он не описывает сложное владение объектом.
CK>это какие же?
Самое простое это неудобные случаи когда время жизни объекта не совпадает со временем жизни переменной.
И например может быть два объекта со счетчиками ссылок, которые нужно удалять вместе, или с более сложной логикой. Или нужно выделить ресурс в середине одной функции, а освободить в середине совсем другой, не связаной напрямую с первой. Я понимаю, что можно исхитриться, но это же неудобно.
Вообще идея связывать время жизни переменной и какие-то операции по освобождению ресурсов довольно сомнительная. Время жизни переменной — это исключительно синтаксическая вещь, а освобождение ресурсов — императивная операция. И писать обертки над функциями только чтобы создать временную переменную, рассчитывая что где-то компилятор ее удалит, это удалять зубы через нос.
lpd>>Может это и ясно, но синтаксис у умных указателей очень громоздкий. И тут начнутся всякие auto, с которыми уже вообще ничего в коде не видно.
CK>Это чем же он громоздкий? Сишные st1->st2.fld3->st4 это значит не громоздко совсем, да?
Ну все эти unique_ptr<Type> по мне очень длинны если их писать по любому поводу, Type * всяко короче.
CK>с помощью ASan довольно тривиально, но вообще это не приходится делать, если правильно проектировать архитектуру, то бишь делать так, чтобы граф зависимостей объектов был ацикличным и направленным (это также неплохо помогает от дедлоков), то что сишечка позволяет иметь кучу циклических ссылок между объектами вовсе не значит что их нужно обязательно создавать и что это есть хорошо
Циклические ссылки могут понадобиться, и не всегда это плохая архитектура. С++ получается ограничивает программиста, или заставляет его думать об освобождении памяти.
lpd>>Я бы предпочел вручную освобождение прописать, хотя если нравится RAII то могу понять.
CK>Явный new/delete или malloc/free в проекте на С++ это чаще всего code smell, нет реально ни одной причины для того, чтобы выделять и освобождать память или создавать и удалять объекты таким способом. Ты так предпочитаешь делать, ок, но для всех остальных в этом нет никакой логики, это просто код с душком.
Я предпочту сборку мусора явному delete/free. Однако городить unique_ptr<>/shared_ptr<> в простых случаях, где не нужен подсчет ссылок, значит делать освобождение памяти неявным без причины, да еще с неудобным синтаксисом. И вот это уже является слепым следованием за фанатиками вроде Майерса.
CK>там не удаление объектов тормозит, а поиск объектов, которые никто не использует и которые можно удалить
Тормозят объекты, выделяемые в большом количестве в цикле или массово. Их и можно удалять вручную, для ускорения сборки мусора. Где-то сборка мусора не подойдет, в таких проектах можно использовать free/delete + умные указатели.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, andyp, Вы писали:
A>Имхо, с if достаточно полезная ошибка, не очень ясно почему именно not equal считается true. А вот свитч — да, хотелось бы, чтобы работало.
Здравствуйте, Шахтер, Вы писали:
PM>>А какая проблема изначально решалась? Я не понял из стартового сообщения.
Ш>Проблема в том, что для использования 3-way comparision нужен тип для записи результатов сравнения. Вот примерно такой.
Ш>
То есть вас по какой-то причине не устраивают константы из стандартной библиотеки, так что вы решили пропатчить ее реализацию, чтобы иметь возможность делать небезопасные неявные приведения к int?
Понятно, что настоящие программисты так не ошибаются, и вам это начем-то реально нужно. Но чем не устраивает менее варварский способ с функцией-переходником типа
CmpResult myFancyOrdering(std::weak_ordering ord)
{
if (ord < 0) return CmpLess;
if (ord == 0) return CmpEqual;
if (ord > 0) return CmpGreater;
}
Здравствуйте, PM, Вы писали:
PM>То есть вас по какой-то причине не устраивают константы из стандартной библиотеки, так что вы решили пропатчить ее реализацию, чтобы иметь возможность делать небезопасные неявные приведения к int?
Оно безопасное.
PM>Понятно, что настоящие программисты так не ошибаются, и вам это начем-то реально нужно.
Сарказм неуместен. У меня долгоживущий проект, в котором используется enum CmpResult и почему-то никаких проблем с безопасностью это не вызывает. Так что проблема безопасности здесь надумана.
PM>Но чем не устраивает менее варварский способ с функцией-переходником типа PM>
PM>CmpResult myFancyOrdering(std::weak_ordering ord)
PM>{
PM> if (ord < 0) return CmpLess;
PM> if (ord == 0) return CmpEqual;
PM> if (ord > 0) return CmpGreater;
PM>}
PM>
Идиотизм. У меня в std::weak_ordering уже лежит переменная с нужным мне значением. Только она приватная. "Небезопасно", а то вдруг я порежусь!
Мне не нужна непрошенная забота о моей безопасности. Особенно такая, которая тупо мешает работать.
lpd>Самое простое это неудобные случаи когда время жизни объекта не совпадает со временем жизни переменной.
это точно также работает и с умными указателями
shared_ptr<Foo> x = ...;
...
x.reset(new Foo());
...
x = y;
...
lpd>И например может быть два объекта со счетчиками ссылок, которые нужно удалять вместе, или с более сложной логикой. Или нужно выделить ресурс в середине одной функции, а освободить в середине совсем другой, не связаной напрямую с первой. Я понимаю, что можно исхитриться, но это же неудобно.
два объекта со счетчиками ссылок которые нужно удалять вместе, ты и на чистом Си не удалишь вместе не нарушив инвариант счетчика ссылок
lpd>Вообще идея связывать время жизни переменной и какие-то операции по освобождению ресурсов довольно сомнительная. Время жизни переменной — это исключительно синтаксическая вещь, а освобождение ресурсов — императивная операция. И писать обертки над функциями только чтобы создать временную переменную, рассчитывая что где-то компилятор ее удалит, это удалять зубы через нос.
как раз наоборот, компилятор не забудет удалить, а вот кое кто предпочитает писать код с утечками, потому что так "проще"
lpd>Циклические ссылки могут понадобиться, и не всегда это плохая архитектура. С++ получается ограничивает программиста, или заставляет его думать об освобождении памяти.
я не говорил что их невозможно реализовать, но как правило это плохая архитектура
lpd>Я предпочту сборку мусора явному delete/free. Однако городить unique_ptr<>/shared_ptr<> в простых случаях, где не нужен подсчет ссылок, значит делать освобождение памяти неявным без причины, да еще с неудобным синтаксисом. И вот это уже является слепым следованием за фанатиками вроде Майерса.
ну вот чуть выше я предложил пример:
auto x = new X();
auto y = new Y(); // new throws exception here
vs
auto x = std::make_unique<X>();
auto y = std::make_unique<Y>();
в первом случае у тебя утечка памяти, потому что если второй new кинет bad_alloc или конструктор Y кинет исключение, объект на который указывает x не будет удален (предпологается что чуть ниже у тебя есть delete x; delete y;, который не выполнится, если будет выброшено исключение). Если ты попробуешь переписать код так, чтобы этого избежать, то получится жуткая каша, с unique_ptr такой проблемы нет
lpd>Тормозят объекты, выделяемые в большом количестве в цикле или массово. Их и можно удалять вручную, для ускорения сборки мусора. Где-то сборка мусора не подойдет, в таких проектах можно использовать free/delete + умные указатели.
— создание объектов в GC языках — очень быстрая операция, удаление тоже (так как у большинства объектов финализаторы пустые), тормозит stop the world фаза сборки мусора, когда GC останавливает все потоки и помечает все достижимые объекты
— free/delete в современных плюсах, как я уже писал, это code smell, попробуй найди хоть одну причину для их использования, кроме личных предпочтений — ничего не получится, т.к. для любого кейса найдется более подходящий и безопасный вариант нежели new/delete или же malloc/free
lpd>Я понимаю, вот совпало, что переменные на стеке компилятор когда-нибудь удаляет, и решили приспособить это дело под освобождение памяти. Это решение явно притянуто за уши, этим мне и не нравится.
он не когда-нибудь удаляет, он их удаляет в порядке обратном их созданию, это называется deterministic destruction и прописано в стандарте явным образом
lpd>Точно также освобождение памяти или ресурсов, искусственно привязанных к переменной, в ее деструкторе — это хак чистой воды, лишенный всякой логики. Если ты этого не видишь, то мои аргументы будут бесполезны.
то что мы можем писать свой код в деструкторе, это тоже так совпало и хак чистой воды? если следовать твоей логике, то писать деинициализацию в деструкторе — хак чистой воды, поэтому класс MyFile должен иметь метод destroy, который нужно явно вызывать перед тем как объект будет удален, а в деструкторе ничего делать не надо, не так ли?
lpd>Я это видел, вариант с прямой проверкой результата вызова оператора new или malloc() кашей не считаю. То, что запись auto x = std::make_unique<X>(); более короткая, не значит что она лучше.
дело не в длине записи, вариант с new не возвращает nullptr, он бросает исключение, проверять его придется так:
try {
x = new X();
y = new Y();
catch (bad_alloc const&) {
// что писать здесь?
}
lpd>Если массовые объекты будут удалены вручную, то stop of the world будет быстрее, о чем я и пишу. В тех редких случаях когда этого недостаточно, можно использовать другие способы управления памятью.
во время stop the world фазы объекты не удаляются (то бишь финализаторы не вызываются и память не освобождается), вместо этого GC всего лишь ходит по указателям и находит живые объекты, представь что у тебя массив на миллиард указателей на объекты, GC пройдет по каждому указателю на объект, заглянет в каждый объект и если там есть указатели, пройдет по ним тоже
и чтобы это работало нормально, компилятор в GC языках вставляет барьер после каждой записи в переменную ссылочного типа, что тоже так себе
lpd>Ну вот десятки лет пока умные указатели не встроили в С++, все (в том числе программисты получше Страуструпа и других С++ников) знали про умные указатели, и почти никто ими не пользовался, кроме как когда они реально были нужны для учета ссылок. А как только Майерс с фанатиками начали пропагандировать unique_ptr<>/shared_ptr<>, сразу выяснилось, что обычный free() code smell.
free это code smell потому что если тебе нужен кусок памяти, то есть std::vector<char> например, если нужно создать объект, то зачем тебе кусок неинициализированной памяти и почему бы не воспользоваться new, если дошло до new, то возникает вопрос, зачем там голый указатель, а не unique_ptr.
Здравствуйте, chaotic-kotik, Вы писали:
CK>Здравствуйте, lpd, Вы писали:
CK>то что мы можем писать свой код в деструкторе, это тоже так совпало и хак чистой воды? если следовать твоей логике, то писать деинициализацию в деструкторе — хак чистой воды, поэтому класс MyFile должен иметь метод destroy, который нужно явно вызывать перед тем как объект будет удален, а в деструкторе ничего делать не надо, не так ли?
Деструктор напрямую связан с объектом по логике. А вот объекты-обертки для освобождения ресурсов или для освобождения памяти — это хак.
lpd>>Я это видел, вариант с прямой проверкой результата вызова оператора new или malloc() кашей не считаю. То, что запись auto x = std::make_unique<X>(); более короткая, не значит что она лучше.
CK>дело не в длине записи, вариант с new не возвращает nullptr, он бросает исключение, проверять его придется так:
Обрабатывать исключение от каждого new отдельно. Но вообще выброс исключения new при нехватке памяти вместо возврата ошибки — сама по себе не самая удобная схема, имхо, впрочем вроде как это поведение можно менять.
CK>free это code smell потому что если тебе нужен кусок памяти, то есть std::vector<char> например, если нужно создать объект, то зачем тебе кусок неинициализированной памяти и почему бы не воспользоваться new, если дошло до new, то возникает вопрос, зачем там голый указатель, а не unique_ptr.
unique_ptr<> освобождается неявно и записывается длинно, лично на мой вкус. Аргументы я свои изложил, тут не вижу смысла дальше спорить.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, Шахтер, Вы писали:
Ш>Простой пример: лексикографическое сравнение.
Суть-то ясна, я к тому, что
if( CmpResult ret=Cmp(hash,obj.hash); ret != std::strong_ordering::equal ) return ret;
имхо даже читабельнее, хотя и больше букв. Можно конечно алиас покороче на std::strong_ordering::equal завести. А вот то, что не работает в свитчах — имхо не есть хорошо.
Здравствуйте, lpd, Вы писали:
lpd>Ну вот десятки лет пока умные указатели не встроили в С++, все (в том числе программисты получше Страуструпа и других С++ников) знали про умные указатели, и почти никто ими не пользовался, кроме как когда они реально были нужны для учета ссылок. А как только Майерс с фанатиками начали пропагандировать unique_ptr<>/shared_ptr<>, сразу выяснилось, что обычный free() code smell. В то время как подавляющее большинство программистов пользуются Java/C# с GC и не страдают этой длиннословной фигней, которую нам впаривают создатели современного С++.
У любой сборки мусора есть свои и преимущества и недостатки. Код с нормальным сборщиком мусора (т.е. не stop-the-world) на многоядерной машине просто порвет любой C++ код со своей традиционностью. Но, только в заданных рамках. А после этих рамок будут рандомные фризы и вообще трудно пойми что.
Традиционный способ проигрывает в короткой перспективе, и сильно — но зато масштабируется без больших сюрпризов, при этом не требует сложной машинерии.
И потом, старый код десятилетней давности насквозь утыкан умными указателями, при чем — у всех свои собственные, один кошернее другого. Так что стандартизация в них — это хороший плюс. И все потихоньку еще переходят на них.
Ну, а их бездумное тыкание совсем везде — это едвали имеет отношение к языку и пропаганде. В нормальном C++ коде большая половина кода, имхо, утыкана обычными указателями, ну или их подвидом — ссылками.
lpd>Циклические ссылки могут понадобиться, и не всегда это плохая архитектура. С++ получается ограничивает программиста, или заставляет его думать об освобождении памяти.
А сишечка, я так понимаю, программиста не ограничивает, и не заставляет думать об освобождении памяти? Ну, ок
Хех, даже ретрограды в гугле, посчитав, что у них "around 70% of our serious security bugs are memory safety problems", начинают наконец-то что-то подозревать "we feel it may be necessary to ban raw pointers from C++" https://www.chromium.org/Home/chromium-security/memory-safety
Здравствуйте, Voivoid, Вы писали:
V>Хех, даже ретрограды в гугле, посчитав, что у них "around 70% of our serious security bugs are memory safety problems", начинают наконец-то что-то подозревать "we feel it may be necessary to ban raw pointers from C++" V>https://www.chromium.org/Home/chromium-security/memory-safety
35%, половина из memory-related багов — это use after free. Умные указатели от неё не спасают.
Вернее так: спасение от use-after-free это GC и/или подсчёт ссылок, что сильно бьет по производительности c-style copy-free кода.
Собственно в статье об этом и написано, бан голых указателей далеко не первый пункт в предлагаемых решениях.
Здравствуйте, gandjustas, Вы писали:
V>>Хех, даже ретрограды в гугле, посчитав, что у них "around 70% of our serious security bugs are memory safety problems", начинают наконец-то что-то подозревать "we feel it may be necessary to ban raw pointers from C++" V>>https://www.chromium.org/Home/chromium-security/memory-safety
G>35%, половина из memory-related багов — это use after free. Умные указатели от неё не спасают.
Здравствуйте, gandjustas, Вы писали:
G>35%, половина из memory-related багов — это use after free. Умные указатели от неё не спасают.
В какой-то степени могут спасти, например когда reset для unique_ptr вызван, но сам unique_ptr еще не разрушен, тогда получим обращение по нулевому указателю. Можно правда обратиться к уже разрушенному unique_ptr по висячей ссылке, но это уже несколько другая проблема.
G>Собственно в статье об этом и написано, бан голых указателей далеко не первый пункт в предлагаемых решениях.
Да вроде как раз о вероятной возможности бана raw указателей и пишут.
"We expect this strategy will boil down to two major strands:
— Significant changes to the C++ developer experience, with some performance impact. (For instance, no raw pointers, bounds checks, and garbage collection.)
— An option of a programming language designed for compile-time safety checks with less runtime performance impact — but obviously there is a cost to bridge between C++ and that new language."
Приоритеты там явно не расставлены, поэтому сложно сказать какой пункт первый, а какой нет.
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, gandjustas, Вы писали:
V>>>Хех, даже ретрограды в гугле, посчитав, что у них "around 70% of our serious security bugs are memory safety problems", начинают наконец-то что-то подозревать "we feel it may be necessary to ban raw pointers from C++" V>>>https://www.chromium.org/Home/chromium-security/memory-safety
G>>35%, половина из memory-related багов — это use after free. Умные указатели от неё не спасают. G>>Вернее так: спасение от use-after-free это GC и/или подсчёт ссылок, что сильно бьет по производительности c-style copy-free кода.
Верну ту часть сообщения, которую вы зачем-то вырезали.
M>Хм. А можно узнать, почему не спасают?
Типичная ситуация:
1) Объект 1 имеет non-owning pointer на объект 2. В текущей версии языка non-owning pointer рекомендуется выражать обычным C-pointer
2) Объект 2 разрушается раньше чем объект 1. Причем эту ситуацию очень легко получить, просто переставив порядок объявлений в классе.
Как эту ситуацию можно решить:
1) Вместо C-pointer передавать везде weak_ptr, а еще в половине методов вписать проверку этих слабых указателей. Но это означает что почти все owning pointer надо сделать shared_ptr и получить большой оверхед на подсчет ссылок.
2) Воспользоваться GC, а-ля https://github.com/hsutter/gcpp, тогда моно механически все указатели поменять на deferred_ptr и повтыкать вызовы collect в дексрукторах объектов верхнего уровня. Но это тоже оверхед, а еще конфликтует с move-семантикой в текущем виде.
Я пишу на С++ плагин к одной одной игрушке, уделяя этому по 2-4 часа в день и дважды за неделю столкнулся с use-after-free, хотя у меня вообще ни одного оператора new нет (вру, один есть и проблема не в нем) и . Потому что use-after-free можно получить с указателями, полученными от OC или COM, особенно когда код асинхронный.
Здравствуйте, Voivoid, Вы писали:
V>Здравствуйте, gandjustas, Вы писали:
G>>35%, половина из memory-related багов — это use after free. Умные указатели от неё не спасают. V>В какой-то степени могут спасти, например когда reset для unique_ptr вызван, но сам unique_ptr еще не разрушен, тогда получим обращение по нулевому указателю. Можно правда обратиться к уже разрушенному unique_ptr по висячей ссылке, но это уже несколько другая проблема.
Это та самая проблема, от которой страдают. Потому что парность new\delete, malloc\free легко отследить на уровне владельца объекта даже без помощи умных указателей. А когда указатель передается куда-то еще, особенно в асинхронный код, то начинается жопа.
Здравствуйте, gandjustas, Вы писали:
G>Как эту ситуацию можно решить:
G>1) Вместо C-pointer передавать везде weak_ptr, а еще в половине методов вписать проверку этих слабых указателей. Но это означает что почти все owning pointer надо сделать shared_ptr и получить большой оверхед на подсчет ссылок.
Что, такой уж большой оверхед? Его кто-нибудь измерял?
G>Типичная ситуация: G>1) Объект 1 имеет non-owning pointer на объект 2. В текущей версии языка non-owning pointer рекомендуется выражать обычным C-pointer G>2) Объект 2 разрушается раньше чем объект 1. Причем эту ситуацию очень легко получить, просто переставив порядок объявлений в классе.
В текущей инкарнации языка как раз таки не рекомендуется иметь non-owning pointer на объект 2, если ты не можешь гарантировать, что объект 1 разрушится раньше объекта 2. Такие вещи как раз принято выражать с помощью shared_ptr/weak_ptr.
G>Как эту ситуацию можно решить:
G>1) Вместо C-pointer передавать везде weak_ptr, а еще в половине методов вписать проверку этих слабых указателей. Но это означает что почти все owning pointer надо сделать shared_ptr и получить большой оверхед на подсчет ссылок. G>2) Воспользоваться GC, а-ля https://github.com/hsutter/gcpp, тогда моно механически все указатели поменять на deferred_ptr и повтыкать вызовы collect в дексрукторах объектов верхнего уровня. Но это тоже оверхед, а еще конфликтует с move-семантикой в текущем виде.
Нужно просто проектировать иерархию объектов с учетом времени жизни объектов и ownership. Скажем, что-то такое, это вполне ОК и без умных указателей:
Здесь объект Workflow разрушится раньше чем s1 и s2, поэтому он может иметь указатели на них. Но если бы все поля класса Foo создавались где-то еще, а не как поля объекта к которым применим принцип deterministic destruction, я бы сделал их умными указателями.
G>Я пишу на С++ плагин к одной одной игрушке, уделяя этому по 2-4 часа в день и дважды за неделю столкнулся с use-after-free, хотя у меня вообще ни одного оператора new нет (вру, один есть и проблема не в нем) и . Потому что use-after-free можно получить с указателями, полученными от OC или COM, особенно когда код асинхронный.
я вот честно говоря не вспомню когда последний раз у меня был такой баг, но я стараюсь проектировать приложения так, чтобы ownership был явным, иерархическим, без циклический зависимостей и тд, это же работает и с асинхронщиной прекрасно, если вспомнить, что lifetime твоих асинхронных обработчиков сообщений привязан к I/O объекту (boost::asio::io_service например, или какому-нибудь сокету или пайпу). В принципе, в boost asio идиоматично пихать в хэндлеры умные указатели.
Здравствуйте, chaotic-kotik, Вы писали:
CK>Здравствуйте, gandjustas, Вы писали:
G>>Типичная ситуация: G>>1) Объект 1 имеет non-owning pointer на объект 2. В текущей версии языка non-owning pointer рекомендуется выражать обычным C-pointer G>>2) Объект 2 разрушается раньше чем объект 1. Причем эту ситуацию очень легко получить, просто переставив порядок объявлений в классе.
CK>В текущей инкарнации языка как раз таки не рекомендуется иметь non-owning pointer на объект 2, если ты не можешь гарантировать, что объект 1 разрушится раньше объекта 2. Такие вещи как раз принято выражать с помощью shared_ptr/weak_ptr.
Но мы же понимаем, что далеко не весь код так написан, как по причинам быстродействия, так и по историческим.
G>>Как эту ситуацию можно решить:
G>>1) Вместо C-pointer передавать везде weak_ptr, а еще в половине методов вписать проверку этих слабых указателей. Но это означает что почти все owning pointer надо сделать shared_ptr и получить большой оверхед на подсчет ссылок. G>>2) Воспользоваться GC, а-ля https://github.com/hsutter/gcpp, тогда моно механически все указатели поменять на deferred_ptr и повтыкать вызовы collect в дексрукторах объектов верхнего уровня. Но это тоже оверхед, а еще конфликтует с move-семантикой в текущем виде.
CK>Нужно просто проектировать иерархию объектов с учетом времени жизни объектов и ownership.
Какбы в проекте старше 5 лет это сложно сделать. Особенно если код асинхронный.
CK>Скажем, что-то такое, это вполне ОК и без умных указателей: CK>
CK>Здесь объект Workflow разрушится раньше чем s1 и s2, поэтому он может иметь указатели на них. Но если бы все поля класса Foo создавались где-то еще, а не как поля объекта к которым применим принцип deterministic destruction, я бы сделал их умными указателями.
Но ошибку довольно легко допустить если поменять порядок объявлений в классе. Компилятор никак не подскажет, умные указатели не помогут.
G>>Я пишу на С++ плагин к одной одной игрушке, уделяя этому по 2-4 часа в день и дважды за неделю столкнулся с use-after-free, хотя у меня вообще ни одного оператора new нет (вру, один есть и проблема не в нем) и . Потому что use-after-free можно получить с указателями, полученными от OC или COM, особенно когда код асинхронный.
CK>я вот честно говоря не вспомню когда последний раз у меня был такой баг, но я стараюсь проектировать приложения так, чтобы ownership был явным, иерархическим, без циклический зависимостей и тд, это же работает и с асинхронщиной прекрасно, если вспомнить, что lifetime твоих асинхронных обработчиков сообщений привязан к I/O объекту (boost::asio::io_service например, или какому-нибудь сокету или пайпу). В принципе, в boost asio идиоматично пихать в хэндлеры умные указатели.
далеко не все используют буст. Я так понимаю что вышупомянутый хром как раз не использует.
Здравствуйте, gandjustas, Вы писали:
G>Это та самая проблема, от которой страдают. Потому что парность new\delete, malloc\free легко отследить на уровне владельца объекта даже без помощи умных указателей. А когда указатель передается куда-то еще, особенно в асинхронный код, то начинается жопа.
Здравствуйте, chaotic-kotik, Вы писали:
CK>В текущей инкарнации языка как раз таки не рекомендуется иметь non-owning pointer на объект 2, если ты не можешь гарантировать, что объект 1 разрушится раньше объекта 2. Такие вещи как раз принято выражать с помощью shared_ptr/weak_ptr.
Где можно прочитать такие рекомендации? Голые владеющие указатели -- да, плохо.
А вот голые невладеющие указатели/ссылки где не рекомендуют использовать?
Ведь weak_ptr -- это не бесплатно. Да и weak_ptr идет в придачу к shared_ptr, а далеко не все объекты создаются через shared_ptr (или для них выгодно создавать shared_ptr).
CK>>Здесь объект Workflow разрушится раньше чем s1 и s2, поэтому он может иметь указатели на них. Но если бы все поля класса Foo создавались где-то еще, а не как поля объекта к которым применим принцип deterministic destruction, я бы сделал их умными указателями. G>Но ошибку довольно легко допустить если поменять порядок объявлений в классе. Компилятор никак не подскажет, умные указатели не помогут.
Можно инициализировать workflow в списке инициализации в конструкторе. Тогда компилятор подскажет. Без этого, достаточно сделать так, чтобы деструктор Workflow не дергал переданные в него указатели в своем деструкторе.
CK>>я вот честно говоря не вспомню когда последний раз у меня был такой баг, но я стараюсь проектировать приложения так, чтобы ownership был явным, иерархическим, без циклический зависимостей и тд, это же работает и с асинхронщиной прекрасно, если вспомнить, что lifetime твоих асинхронных обработчиков сообщений привязан к I/O объекту (boost::asio::io_service например, или какому-нибудь сокету или пайпу). В принципе, в boost asio идиоматично пихать в хэндлеры умные указатели. G>далеко не все используют буст. Я так понимаю что вышупомянутый хром как раз не использует.
Тут дело не в бусте, а в принципе. В асинхронном коде у тебя все равно есть объект, который дергает асинхронно хэндлеры, скажем это thread pool какой-нибудь. Нам нужно обеспечить одну гарантию, чтобы в случае остановки нашего thread pool все находящиеся в очереди хэндлеры были вызваны с кодом ошибки (напирмер ERR_CANCELED), ну или альтернативно — чтобы они все были удалены. Дальше я уже могу сделать так, чтобы время жизни объектов, с которыми работают мои хэндлеры было связано либо с временем жизни thread pool-a, либо самого хэндлера.
Пример: хэндлер использует объект Cache, общий для всех хэндлеров, при этом Cache и ThreadPool являются членами одного класса. При этом хэндлер может иметь умные указатели на per-request данные, которые почистятся если thread pool остановят.
В общем, я не говорю что это панацея и не хочу никого поучать, но явно продумывать ownership и lifetimes мне всегда очень помогало.
Здравствуйте, so5team, Вы писали:
S>Где можно прочитать такие рекомендации? Голые владеющие указатели -- да, плохо. S>А вот голые невладеющие указатели/ссылки где не рекомендуют использовать?
не использовать, а хранить, делать членами класса и тд
просто передать невладеющий указатель в ф-ю, которая будет его использовать пока работает, это норм
передавать его в конструктор объекта и хранить в одном из полей — не норм
S>Ведь weak_ptr -- это не бесплатно. Да и weak_ptr идет в придачу к shared_ptr, а далеко не все объекты создаются через shared_ptr (или для них выгодно создавать shared_ptr).
Здравствуйте, Marty, Вы писали:
M>Здравствуйте, gandjustas, Вы писали:
G>>Это та самая проблема, от которой страдают. Потому что парность new\delete, malloc\free легко отследить на уровне владельца объекта даже без помощи умных указателей. А когда указатель передается куда-то еще, особенно в асинхронный код, то начинается жопа.
M>И тут выручают умные указатели
Конечно выручают, путем оверхеда на кадое присванивание\передачу параметром. А также утечки памяти при не очень удачных замыканиях. Не говоря уже о том, что с помощью лябд легко сделать циклические ссылки.
Здравствуйте, chaotic-kotik, Вы писали:
CK>не использовать, а хранить, делать членами класса и тд CK>просто передать невладеющий указатель в ф-ю, которая будет его использовать пока работает, это норм CK>передавать его в конструктор объекта и хранить в одном из полей — не норм
Пусть в такой формулировке. Где подобные рекомендации можно прочитать?
S>>Ведь weak_ptr -- это не бесплатно. Да и weak_ptr идет в придачу к shared_ptr, а далеко не все объекты создаются через shared_ptr (или для них выгодно создавать shared_ptr).
CK>конечно не бесплатно (не утверждал обратное)
Поскольку не бесплатно, то значит это не будут использовать по вполне объективным причинам.
Здравствуйте, chaotic-kotik, Вы писали:
CK>Тут дело не в бусте, а в принципе. В асинхронном коде у тебя все равно есть объект, который дергает асинхронно хэндлеры, скажем это thread pool какой-нибудь. Нам нужно обеспечить одну гарантию, чтобы в случае остановки нашего thread pool все находящиеся в очереди хэндлеры были вызваны с кодом ошибки (напирмер ERR_CANCELED), ну или альтернативно — чтобы они все были удалены. Дальше я уже могу сделать так, чтобы время жизни объектов, с которыми работают мои хэндлеры было связано либо с временем жизни thread pool-a, либо самого хэндлера.
Не только в принципе, но и в библиотеке (в данном случае в бусте).
те же самые умные указатели существовали двано, но мало кто торопился их использовать, пока они не попали в STL.
Аналогично в STL сейчас отсуствуют абстрации, а также отсутствуют рекомендации для работы с асинхронным кодом.
CK>В общем, я не говорю что это панацея и не хочу никого поучать, но явно продумывать ownership и lifetimes мне всегда очень помогало.
Ну богатым и здоровым всегда был лучше, чем бедным и больным. Тем не менее проблемы объективно существуют и никакого штатного способа разрешения их нет.
CK>Можно инициализировать workflow в списке инициализации в конструкторе. Тогда компилятор подскажет. Без этого, достаточно сделать так, чтобы деструктор Workflow не дергал переданные в него указатели в своем деструкторе.
Можно сделат что угодно, но это означает что устройство класса Foo начинает влиять на класс Workflow. А последний вообще может быть вам недоступен для изменения.
Это кстати громадная проблема которую я заметил в C++. Я три или четыре раза переписывал один и тот же метод, потому вызывающий код менялся. логика работы оставалась, а менялся способ работы с объектом: ссылки, умные указатели итд.
Здравствуйте, gandjustas, Вы писали:
G>Это кстати громадная проблема которую я заметил в C++. Я три или четыре раза переписывал один и тот же метод, потому вызывающий код менялся. логика работы оставалась, а менялся способ работы с объектом: ссылки, умные указатели итд.
Спасение утопающих — дело рук самих утопающих. Я даже свою библиотеку с умными указателями писать начал (C++ Object Token Library
Здравствуйте, so5team, Вы писали:
S>Пусть в такой формулировке. Где подобные рекомендации можно прочитать?
наш code guide таки прямо это не рекомендует, если что-то общедоступное, то есть core guidelines, в котором емнип а) рекомендуется использовать смарт поинтеры для управления временем жизни объектов б) не рекомендует использовать не владеющие указатели/ссылки, которые являются алиасами для объектов, временем жизни которых управляют смарт-поинтеры
Здравствуйте, chaotic-kotik, Вы писали:
S>>Пусть в такой формулировке. Где подобные рекомендации можно прочитать?
CK>наш code guide таки прямо это не рекомендует
А ваш -- это чей?
CK>б) не рекомендует использовать не владеющие указатели/ссылки, которые являются алиасами для объектов, временем жизни которых управляют смарт-поинтеры
Это несколько другое, нежели:
В текущей инкарнации языка как раз таки не рекомендуется иметь non-owning pointer на объект 2, если ты не можешь гарантировать, что объект 1 разрушится раньше объекта 2.
Поскольку первоначальное ваше утверждение можно применять и к объектам, которые вообще не создаются динамически, но на которые, тем не менее, ссылаются.
Здравствуйте, so5team, Вы писали:
S>Это несколько другое, нежели: S>
В текущей инкарнации языка как раз таки не рекомендуется иметь non-owning pointer на объект 2, если ты не можешь гарантировать, что объект 1 разрушится раньше объекта 2.
S>Поскольку первоначальное ваше утверждение можно применять и к объектам, которые вообще не создаются динамически, но на которые, тем не менее, ссылаются.
не то чтобы я стремился тут дать строгое определение, но для объектов, которые не создаются динамически, я могу гарантировать требуемый lifetime
Здравствуйте, smeeld, Вы писали:
S>> С древней кодобазой, на 80% состоящей из велосипедов в которых уже никто не разбирается. S>99% всех промышленных программных систем, обсуживающих мир, представлено именно этим кодом.
Система, занимающая примерно 40% всего рынка SCADA и до 90% рынка систем управления питанием для общественных зданий и датацентров, написана на плюсах (c применением boost) и сишарпе.
А вот проприетарные и не очень протоколы, которая эта система вынуждена использовать, и правда представлены "именно этим кодом". И вот в них баг на багах сидит и на велосипедах друг друга погоняет, и не разваливается это все к такой-то матери только потому, что в конторах, "поддерживающие" этот, с позволения сказать, код, до сих пор на зарплате сидит дедушка, задача которого — завуалированно отвечать на запросы ответами в стиле "ты это дерьмо так не юзай и вот так не вызывай, а то снег башка попадет".
S>А всякие хеллоуворлды даром никому не нужны, на каком бы распрекрасном C++ они не были написаны.
Здравствуйте, Kluev, Вы писали:
K>Пользуясь случаем спрошу как в современном С++ сделать опережающее описание вложенного класса?
Ответ будет зависеть от того, что вы понимаете под "опережающее описание вложенного класса" и того, зачем вам это нужно.
Но, есть подозрение, что выглядеть будет почти так же, как и в C++98, только вместо typedef будет использоваться using.
S>И где это нужно? Ну, за исключением кидания какашками на форуме?
Грубо говоря весь С++ это собрание ненужных и недоделанных вещей. Но речь не об этом. В язык ввели вложенные классы как минимум с С++98. И 20 чертовых лет не могут сделать для них опережающее описание (forward declaration) чтобы ими можно было полноценно пользоваться.
Здравствуйте, lpd, Вы писали:
lpd>Ну вот десятки лет пока умные указатели не встроили в С++, все (в том числе программисты получше Страуструпа и других С++ников) знали про умные указатели, и почти никто ими не пользовался, кроме как когда они реально были нужны для учета ссылок.
Это не так. Фактически умные указатели (ака ресурсы с подсчётом пользователей) были придуманы и использовались задолго до шаблонного синтаксиса в С++. В С++ умные указатели широко использовались в коммерческом софте начиная где-то между 1995-2000 годах.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, lpd, Вы писали:
lpd>>Ну вот десятки лет пока умные указатели не встроили в С++, все (в том числе программисты получше Страуструпа и других С++ников) знали про умные указатели, и почти никто ими не пользовался, кроме как когда они реально были нужны для учета ссылок.
BFE>Это не так. Фактически умные указатели (ака ресурсы с подсчётом пользователей) были придуманы и использовались задолго до шаблонного синтаксиса в С++. В С++ умные указатели широко использовались в коммерческом софте начиная где-то между 1995-2000 годах.
Я в курсе, перечитай что цитируешь.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, lpd, Вы писали:
CK>>то что мы можем писать свой код в деструкторе, это тоже так совпало и хак чистой воды? если следовать твоей логике, то писать деинициализацию в деструкторе — хак чистой воды, поэтому класс MyFile должен иметь метод destroy, который нужно явно вызывать перед тем как объект будет удален, а в деструкторе ничего делать не надо, не так ли? lpd>Деструктор напрямую связан с объектом по логике. А вот объекты-обертки для освобождения ресурсов или для освобождения памяти — это хак.
Следовательно, все, кто использует RAII — хакеры.
А что-бы вы предпочли взамен RAII? Секцию кода, который выполняется при каждом выходе из функции? А как этот код получит доступ к переменным/состоянию внутренней части кода?
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, lpd, Вы писали:
lpd>>Деструктор напрямую связан с объектом по логике. А вот объекты-обертки для освобождения ресурсов или для освобождения памяти — это хак.
BFE>Следовательно, все, кто использует RAII — хакеры.
BFE>А что-бы вы предпочли взамен RAII? Секцию кода, который выполняется при каждом выходе из функции? А как этот код получит доступ к переменным/состоянию внутренней части кода?
Открывать ресурс в начале функции, а освобождать в конце этой же функции — это совсем лубок какой-то из маленьких программок-примеров. Вообще, файл — это абстракция ОС, управляемая по хэндлу, и не вижу смысла путать его с локальными переменными — абстракциями С++.
А динамическая память — это вообще не ресурс в этом смысле. Я не против умных указателей там, где действительно нужен подсчет ссылок, хотя чаще была бы полезней сборка мусора.
Ну и вообще можно сколько угодно оттачивать инструменты, но если строитель не умеет строить, то ничего не выйдет. Язык программирования и его фичи — это далеко не самое главное. Поэтому никакие фичи С++ не исправят плохую архитектуру программы, сколько этот язык не будут расширять.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, lpd, Вы писали:
BFE>>А что-бы вы предпочли взамен RAII? Секцию кода, который выполняется при каждом выходе из функции? А как этот код получит доступ к переменным/состоянию внутренней части кода?
lpd>Открывать ресурс в начале функции, а освобождать в конце этой же функции — это совсем лубок какой-то из маленьких программок-примеров.
Нет. Это обычное дело для конфиг файлов.
lpd>Вообще, файл — это абстракция ОС, управляемая по хэндлу, и не вижу смысла путать его с локальными переменными — абстракциями С++.
А почему именно файл? А если речь про mutex, к примеру?
lpd>Ну и вообще можно сколько угодно оттачивать инструменты, но если строитель не умеет строить, то ничего не выйдет. Язык программирования и его фичи — это далеко не самое главное. Поэтому никакие фичи С++ не исправят плохую архитектуру программы, сколько этот язык не будут расширять.
Ну раз фичи языка не важны, значит с RAII в С++ всё нормально.
Здравствуйте, lpd, Вы писали:
lpd>С lock_guard на мой взгляд нужно искать по коду где же этот мьютекс освободится, писать дополнительные блоки {}, поэтому проще явно написать unlock().
Но ведь ровно наоборот, если у вас в коде есть явные unlock(), то придётся просматривать весь код в поисках не только unlock(), но и всех выходов из функции.
lpd>Да и с мьютексами обычно проблемы гораздо сложнее, чем просто забыть разлочить. Но это вопрос вкуса, не вижу большой разницы для мьютексов.
Ну не знаю. У меня с мьютексами вообще никаких проблем никогда не было, хотя все приложения за последние 15 лет — многопоточные. Если у вас проблемы с мьютексами, значит у вас в архитектуре что-то не правильно написано.
Здравствуйте, Kluev, Вы писали:
K>Например iostream. По словам Страуструпа была написанная кем-то на спор.
Цитату бы.
K>Или stl. Минуя продакшн сразу в стандарт.
Если вы не в курсе, то STL допиливался до состояния, в котором его приняли в стандарт, несколько лет. И в 1996-1997-ом годах свободные реализации STL (вроде бы от RogueWare) уже активно использовались в продакшене.
K>>>Приведите хоть один реальный случай случая когда нельзя было бы обойтись префиксами.
S>>Попробуйте выразить std::chrono::milliseconds через префиксы. Или std::chrono::steady_clock::time_point. А так же попробуйте придумать на префиксах адекватную замену для, например, using namespace std::chrono_literals.
K>Да в легкую. Например std_chrono_milliseconds.
Вы в очередной раз несете бред. Уж сами решайте достаточно ли вы взрослый, чтобы принять то, что вас никто не будет ублажать и ваш бред открыто называют бредом. Или нет и будете опять намекать на инфантилизм собеседника.
В следующий раз, прежде чем решитесь еще такую пургу погнать публично, потрудитесь обосновать, почему вас следует воспринимать всерьез.
K>Можете возразить, что длинно, но до auto stl-юзеры писали километровые std::map<..........., ...........>::const_iterator и не потели.
Многие знали про typedef.
K>Что касается литералов, то это фантастически бесполезная лабуда.
Очередной бред.
K>Вы опять на личности хотите перейти?
Еще раз: когда вы публично несете бред вам на это публично же и указывать будут.
K>Я вам привел в пример один из неисправленных дефектов языка.
Позволю себе напомнить, что вы ни раз (ни разу, Карл!) не привели примера реальной ситуации, где этот "дефект языка" мог хоть как-нибудь сказаться.
Что в сочетании с другими бредовыми высказываниями говорит о том, что вы, в лучшем случае, жирный тролль.
Здравствуйте, Kluev, Вы писали:
K>>>Когда у вас в языке нет: K>>>рефлексии BFE>>А можно пример продукта, где широко используется рефлексия и который используется более 10 лет? K>В objective-c рефлексия с 1983г
Допустим. Повторюсь: можете назвать продукт (не язык, а программу), где широко используется рефлексия и который используется более 10 лет?
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>Вы не привыкли джентльменам верить на слово?
S>Нет. Тем более, что здесь нет джентельменов.
K>>C's printf family of functions is an effective and often convenient I/O mechanism. K>>It is not, however, type-safe or extensible to user-defined types (classes and enumera- K>>tions). Consequently, I started looking for a type-safe, terse, extensible, and efficient K>>alternative to the printf family. Part of the inspiration came from the last page and K>>a half of the Ada Rationale [Ichbiah,1979], which argues that you cannot have a terse K>>and type-safe I/O library without special language features to support it. I took that as K>>a challenge. The result was the stream I/O library that was first implemented in 1984 K>>and presented
S>Все это сильно отличается от вашей интерпретации "По словам Страуструпа была написанная кем-то на спор." Потому что "я воспринял это как вызов" и "я сделал это наспор" сильно различаются по смыслу.
Никакой принципиальной разницы нет т.к. мотивация была не рациональной, а эмоциональной. Личное спортивное достижение, которое нужно было скромно положить на полочку, а не тащить в стандарт языка.
K>>Самой важной причиной является то, что stl криво спроектированная библиотека. В ней плохо практически все. Даже индекс и размер контейнера и тот умудрилось сделать unsigned создав программистам кучу проблем на ровном месте. Наличие совершенно бесполезных надуманных вещей таких как valarray выдает в ней академическую разработку, написанную для диссера или научной статьи. В качестве стандартной библиотеки языка эта экспериментальная разработка категорически не годится.
S>Можно предположить, что вы считаете свое мнение непогрешимым и единственно правильным. S>Но это не так. И авторы STL не единственные люди, которые считают, что размеры и индексы должны быть беззнаковыми.
Конечно, считаю правильным и единственно верным. И авторы java так считают. И авторы С#. В них индексы знаковые. Это вполне разумное и очевидное решение чтобы избежать проблем смешанной арифметики
K>>Знаете есть вещи хорошо сделанные, которыми приятно пользоватся и писать собственный велосипед желания не возникнет. stl напротив образчик плохого дизайна и анти-эстетики.
S>Например? Неужели Qt?
K>>И по вашему в том числе. Нотацию с префиксами вы сами забраковали постами выше,
S>Нотация с префиксами -- это негибко и немасштабируемо. Тут даже нет места для моего субъективизма.
Просто у вас не хватает воображения. Есть проекты на ~100Мб кода которые с префиксами вполне живут и хорошо масштабируются.
K>>ну а класс storage в пространстве имен storage и комментариев не требует.
S>Речь не про storage в пространстве storage. Речь про взаимоотношения storage и blob. Но для человека с такой непогрешимой верой в собственное мнение, может быть и непонятно.
K>>>>Но для вложенного класса нет опережающего описания и его потребуется всегда включать через #include.
S>Пипец. А вот это что в примере, который вы, очевидно, не поняли: S>
S>class A {
S> struct impl;
S> std::unique_ptr<impl> impl_;
S>
K>>
K>>struct Storage;
K>>void foo(Stroage *stg);
K>>
Вот теперь попробуйте вынести его за пределы класса.
S>Где здесь использование?
K>>С вложенным классом Storage::Blob такой номер не пройдет т.к. в языке С++ нет механизма опережающих описаний. Это баг уровня языка который нужно исправлять. Как бы вы тут не распинались, что это и не нужно.
K>>
S>Так может вы наконец-то разродитесь примером того, где это реальная проблема?
Везде где вы хотите объявить указатель или ссылку на вложенный класс, но не хотите включать хедер с классом.
K>>То с какой скоростью и как комитет проектирует этот язык напоминает издевательство. Было бы честнее либо заморозить С++ в актуальной версии и начать новый С++2.0 несовместимый со старым как это сделали в питоне, либо совсем отказаться от разработки языка объявив его deprecated. С моей точки зрения существующий труп смысла насиловать уже не имеет.
S>Ну так сделайте. Кто вам мешает? S>C++ развивается силами добровольцев. Если есть идеи вы можете продвинуть их в C++. S>Но есть ощущение, что дальше самовлюбленного высказывания собственного бреда на RSDN, вы дальше пройти не сможете. В принципе.
Мне есть на что тратить время.
K>>Эти литералы сделаны в угоду нескольким фрикам, которым не терпелось добавить в stl константы типа в минуте 60 секунд.
S>Значит этих фриков, как минимум, на одного больше.
Вот это то и плохо.
K>>Попбробуйте завести литерал Н/м^2 и не говорите что нинужно. Секунды завезли, а чем паскали хуже?
S>Ну заведите. Кто вам запрещает?
Как минимум то, что в С++ нет оператора возведения в степень
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Kluev, Вы писали:
K>>>>Когда у вас в языке нет: K>>>>рефлексии BFE>>>А можно пример продукта, где широко используется рефлексия и который используется более 10 лет? K>>В objective-c рефлексия с 1983г
BFE>Допустим. Повторюсь: можете назвать продукт (не язык, а программу), где широко используется рефлексия и который используется более 10 лет?
Здравствуйте, Kluev, Вы писали:
K>Конечно, считаю правильным и единственно верным.
На этих словах смыл разговора с вами окончательно пропал. Бесполезно объяснять что-то персонажам, не допускающим существование альтернативных точек зрения.
Тем более, что даже примеров кода из вас вытащить не представляется возможным.
Здравствуйте, B0FEE664, Вы писали:
BFE>Да неужели? Вот, возьмём Eclipse. Допустим с его помощью я редактирую текстовый файл. Как и для чего используется Рефлексия в этом случае?
Рефлексия используется для DI-контейнеров. Самое очевидное применение. Затем идёт сериализация-десериализация.
Здравствуйте, Слава, Вы писали:
BFE>>Да неужели? Вот, возьмём Eclipse. Допустим с его помощью я редактирую текстовый файл. Как и для чего используется Рефлексия в этом случае? С>Рефлексия используется для DI-контейнеров. Самое очевидное применение.
Зачем при редактировании текстового файла DI-контейнер?
С> Затем идёт сериализация-десериализация.
Сериализация-десериализация чего?
Обратная совместимость при этом поддерживается на протяжении всех 10-и лет?
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Kluev, Вы писали:
K>>Вот здесь тысячи их K>>https://apps.apple.com/ru/genre/mac/id39?mt=12 BFE>И как же они использую рефлексию и для чего?
Здравствуйте, Kluev, Вы писали:
K>Здравствуйте, YuriV, Вы писали:
YV>>Здравствуйте, Zhendos, Вы писали:
Z>>>Так идея в том чтобы storage тоже имел "forward declaration" наряду с blob.
Z>>>https://stackoverflow.com/questions/951234/forward-declaration-of-nested-types-classes-in-c
YV>>Это не идея, а непонимание. Полный тип в C++ это его имя и описание его структуры. А "forward declaration" объявляет лишь имя типа (incomplete type) структура которого сейчас неизвестна и поэтому получить доступ к структуре (storage::blob) incomplete type через его имя невозможно. Тут всё логично и никакой "дыры" в языке нет. Можно ввести в язык расширяемые классы, ну как namespace может расширяться в разных единицах трансляции новыми declaration/definition. Этакая альтернатива наследованию, но к чему это может привести прогнозировать сложно.
K>Неверно. Вложенный тип не является частью типа, а находится в его пространстве имен. K>Нет никаких проблем чтобы сделать опережающее описание следующим образом:
K>
K>class storage;
K>class storage::blob;
K>
Верно. Объявление вложенного типа находиться внутри "member specification" или class body или пространства имён класса — как угодно, которое очевидно отсутствует в "forward declaration". Так что с точки зрения языка всё верно. Иначе чем nested typedefs лучше nested data members, тогда и их надо разрешить и методы и т.д. Такие вещи можно делать в темплейтных классах и то ограниченно. Например этот код не скомпилиться, потому что в точке использования тип C всё ещё неопределён.
template <typename T> struct A {
using type = typename T::C; // error
};
struct B : A<B> {
using C = int;
};
S>Если вы не в курсе, то STL допиливался до состояния, в котором его приняли в стандарт, несколько лет. И в 1996-1997-ом годах свободные реализации STL (вроде бы от RogueWare) уже активно использовались в продакшене.
RogueWave, если быть точным. В бормановском билдере 1, 3, и может и 5, например
K>Если вы не в курсе от раннего stl-мазохизма в продакшене активно отказывались и пересаживались на собственные разработки. Это уже веский повод не торопится с добавлением такой сомнительной библиотеки.
Если вы не в курсе, то к моменту даже раннего stl многие уже плотно сидели на своих велосипедах
Здравствуйте, T4r4sB, Вы писали:
S>>Но это не так. И авторы STL не единственные люди, которые считают, что размеры и индексы должны быть беззнаковыми.
TB>Вообще-то они уже признали, что это была ошибка.
Если под "они" подразумеваются авторы STL, то где об этом можно прочитать?
А вообще речь шла о том, что кроме авторов STL есть разработчики, которые находят логичным использование беззнаковых чисел для размеров и индексов. Т.е. авторы STL вовсе не были "белыми воронами".
Здравствуйте, Marty, Вы писали:
S>>Если вы не в курсе, то STL допиливался до состояния, в котором его приняли в стандарт, несколько лет. И в 1996-1997-ом годах свободные реализации STL (вроде бы от RogueWare) уже активно использовались в продакшене.
M>RogueWave, если быть точным. В бормановском билдере 1, 3, и может и 5, например
Некоторые умельцы прикручивали STL от RogueWave к Watcom 10 и 11.
Здравствуйте, so5team, Вы писали:
S>>>Если вы не в курсе, то STL допиливался до состояния, в котором его приняли в стандарт, несколько лет. И в 1996-1997-ом годах свободные реализации STL (вроде бы от RogueWare) уже активно использовались в продакшене.
M>>RogueWave, если быть точным. В бормановском билдере 1, 3, и может и 5, например
S>Некоторые умельцы прикручивали STL от RogueWave к Watcom 10 и 11.
Еще вот прямо сейчас смотрю в хидеры пятого кейла для арма, который ARMCC, а не ARMCLANG, и вижу
* Copyright (c) 1994-2001 Rogue Wave Software, Inc. All Rights Reserved.
YV>Верно. Объявление вложенного типа находиться внутри "member specification" или class body или пространства имён класса — как угодно, которое очевидно отсутствует в "forward declaration". Так что с точки зрения языка всё верно.
Неверно. Пространство имен класса очевидно присутствует в опережающем описании. Вот оно:
classstorage;
Поэтому нет никаких проблем с объявлением вложенного класса.
YV>Иначе чем nested typedefs лучше nested data members, тогда и их надо разрешить и методы и т.д.
У атрибутов смещение в объекте зависит от порядка декларации. Поэтому разрешить опережающее описание не статических атрибутов в рамках языка С++ невозможно.
Здравствуйте, Kluev, Вы писали:
K>За этим "логичным" решением стоит целый лес граблей, ладно когда его не видит обычный разработчик, но когда "близорукость" у создателей стандарт пиши пропало.
За любым решением стоит целый лес граблей. Разница между нами в том, что вы безоговорочно считаете свою точку зрения единственно правильной, тогда как я считаю, что оба подхода имеют право на существование и у каждого есть плюсы и минусы. В C++ исторически сложилось так. И многие действующие разработчики до сих пор не видят в этом проблемы.
В Java сложилось по другому. Так изначально беззнаковых чисел вообще не было (а может и сейчас нет). Посему сделать беззнаковые индексы там нельзя было в принципе. Так же Java никогда не ориентировалась, например, на 16-битовые платформы. Тогда как C++ вполне себе существовал и работал на таких.
Здравствуйте, so5team, Вы писали:
S>Любопытно. В сообщении, на которое вы ответили, был вопрос о том, где можно прочитать про признание ошибки. Так же, без упреков в чью-то сторону, было сказано, что есть люди, который находят смысл в беззнаковых индексах и размерах.
S>Ничего конструктивного и полезного вы не сказали, но зачем-то завели речь про "жрать говно".
Я не буду доказывать, что якобы мой комментарий про говно корректен, очевидно, что это не так.
Тут где-то в соседней теме уже изрядно пофлеймили на тему беззнаковых индексов, которые даже обрытный цикл заставляют писать через какие-то странные идиомы, а я устал.
Здравствуйте, T4r4sB, Вы писали:
TB>Тут где-то в соседней теме уже изрядно пофлеймили на тему беззнаковых индексов, которые даже обрытный цикл заставляют писать через какие-то странные идиомы, а я устал.
TB>http://rsdn.org/forum/flame.comp/7728838.flat.1
Во-первых, сам по себе спор на RSDN ничего не доказывает. У одних свое мнение, у других другое. Точно так же можно бесконечно спорить про big endian vs little endian. С таким же примерно итогом.
Во-вторых, безотносительно того, какого мнения придерживаетесь лично вы, мне интересно узнать про подтверждение вот этих ваших слов:
Здравствуйте, so5team, Вы писали:
S>Во-вторых, безотносительно того, какого мнения придерживаетесь лично вы, мне интересно узнать про подтверждение вот этих ваших слов:
S>
Вообще-то они уже признали, что это была ошибка.
Там в той теме я где-то выкладывал видос с мёртвым страусом, который про это упоминал.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>За этим "логичным" решением стоит целый лес граблей, ладно когда его не видит обычный разработчик, но когда "близорукость" у создателей стандарт пиши пропало.
S>За любым решением стоит целый лес граблей. Разница между нами в том, что вы безоговорочно считаете свою точку зрения единственно правильной, тогда как я считаю, что оба подхода имеют право на существование и у каждого есть плюсы и минусы. В C++ исторически сложилось так. И многие действующие разработчики до сих пор не видят в этом проблемы.
Это не значит, что все решения одинаково плохие. Минусов у беззнаковых индексов больше. Знаковые можно упрекнуть лишь в том, что они адресуют в два раза меньше.
S>В Java сложилось по другому. Так изначально беззнаковых чисел вообще не было (а может и сейчас нет). Посему сделать беззнаковые индексы там нельзя было в принципе. Так же Java никогда не ориентировалась, например, на 16-битовые платформы. Тогда как C++ вполне себе существовал и работал на таких.
На 16-ти битах в условиях нехватки оперативной памяти stl последнее, что понадобится программисту. Поэтому говорить, что беззнаковый индекс был сделан с оглядкой на 16-битные архитектуры. Мне кажется, что это просто смешно.
Здравствуйте, Kluev, Вы писали:
K>Это не значит, что все решения одинаково плохие. Минусов у беззнаковых индексов больше. Знаковые можно упрекнуть лишь в том, что они адресуют в два раза меньше.
Повторю еще раз что это значит: это значит, что вы считаете свое мнение единственно верным.
Причем, складывается ощущение, что во многом потому, что вы недостаточно широко смотрите по сторонам.
Здравствуйте, so5team, Вы писали:
TB>>Там в той теме я где-то выкладывал видос с мёртвым страусом, который про это упоминал.
S>Есть какая-то особая доблесть в том, чтобы за глаза обзывать так немолодого человека, который вообще ни сном ни духом про RSDN-овские разборки?
Да ладно, это уже давно прилипшее погоняло, ничего обидного тут нет, как и желания обидеть страуса
K>На 16-ти битах в условиях нехватки оперативной памяти stl последнее, что понадобится программисту. Поэтому говорить, что беззнаковый индекс был сделан с оглядкой на 16-битные архитектуры. Мне кажется, что это просто смешно.
Ну, STMка хоть и 32ух битная, но памяти там бывает весьма мало. На младших чуть ли не 4 кб оперативы (ну, как минимум, 32 кб точно есть камешки). И ничего, вполне STL используется. Был бы C++ для C51, тоже за милую душу использовал бы stl.
А уж во времена становления C++ 16битные платформы вполне себе мейн стрим были. Так что твой аргумент точно фтопку
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, YuriV
S>Может тогда вы приведете пример ситуации, где невозможность сделать forward declaration для вложенного типа является реальной проблемой?
S>У Kluev-а пока не получилось.
А она и не является таковой. Здесь вопрос чисто академический — почему не дать такую возможность, если она выглядит логично и не несёт серьёзных трудностей в реализации? Я никогда не сталкивался с нуждой так ревностно контролировать включение хидеров и так упорото прятать реализацию. Тем более, лично мне, непонятно зачем использовать классы если данные из них будут обрабатываться отдельными функциями, не методами, которым нужно обеспечить доступ к этим данным. Если внутри вызываются методы класса, то я вижу один вариант — это предоставление кода без детализации внутренней структуры (даже интерфейсов классов), все потроха, в т.ч. декларации и определения классов находятся внутри библиотеки, наружу торчит только набор сигнатур функций. Это и сейчас делается спокойно, только с фиксацией интерфейсов классов. Лично мне это не нужно, поэтому с такой проблемой я никогда не сталкивался. Если эту возможность ввести, то 99.9(9)% процентов программеров её не заметят. Короче с точки зрения чистоты языка такая возможность нужна, с точки зрения прагматики — мне безразлично.
Здравствуйте, YuriV, Вы писали:
YV>Если эту возможность ввести, то 99.9(9)% процентов программеров её не заметят.
В том-то и дело, что на практике проблемы-то и нет. И даже в тех редких случаях, когда что-то подобное требуется, то есть способы это обойти.
YV>Короче с точки зрения чистоты языка такая возможность нужна, с точки зрения прагматики — мне безразлично.
С другой стороны, C++ и так сборная солянка всякого разного и разнообразного. Добавлять что-то новое опасно, если это реально не нужно.
Яркий пример: uniform intialization syntax. Вроде бы хорошую штуку сделали. Но хотели как лучше, а получилось как всегда.
TB>Там в той теме я где-то выкладывал видос с мёртвым страусом, который про это упоминал.
Страуструп, конечно, голова, но все-таки не великодушный пожизненный диктатор. И его мнение в очередной войне тупо- и остроконечников не решающее. Я недавно читал где-то дискуссию про одно из его предложений в стандарт, которая свелась к тому, что авторитет не должен превалировать над техническими аргументами.
Я думаю, компромисс с введением `std::ssize()` не принесет удовлетворения тем кто привык использовать int для индексов — Они сделали дерьмо опять
Здравствуйте, YuriV, Вы писали:
YV>В общем, я просмотрел инфу по поводу forward nested class declaration и беру свои слова обратно. Я согласен с Kluev — все проблемы, которые якобы возникают от такого нововведения смехотворны. Возникающие ошибки (типа защищённого или приватного последующего определения вложенного класса или отсутствия одного из определений в доступных для компиляции единицах трансляции) описываются стандартными сообщениями компилятора/линкера. Вот здесь вердикт Trip Report: C++ Standards Meeting in Jacksonville, February 2016
.. YV>Но никто этим предложением не занимался, видимо все обходятся friend class'ами и данное предложение не толкают активно.
Так в чем загвоздка, подберите упавшее знамя, и вперёд, в комитет, дорабатывать эту важную вещь! Может быть даже РГ21 вам поможет в проталкивании...
YV>И добавлю относительно комитета, это ИМХО и оно никак не связано с вышеупомянутыми вложенными классами. Ниже по ветке я постил "другое" мнение о пути развития C++. Добавлю лишь, что у сегодняшнего комитета полностью отсутствует стратегическое целепологание, а точнее "недемократическая" компетентная группа способная принимать окончательные волевые стратегические решения о пути развития языка. Отсюда принятие фич ради фич и фич, которые интенсивнее педалируют без оглядки на развитие самого языка, на изменение подходов к программированию на этом языке, на современные требования к интеграции языка в инфраструктуру разработки.
А у вас есть такой стратегический план? Было бы любопытно ознакомиться с этим документом.
Здравствуйте, Kluev, Вы писали:
K>Не добавлять новое, а исправлять баги. Не хотят исправлять, пусть честно объявляют вложенные классы deprecated, чтобы программисты не попадались на грабли.
ИМХО, невозможность сделать предварительное объявление вложенного класса за пределами обрамляющего — еще не повод объявлять вложенные классы deprecated. Кстати, с обычными невложенными классами совершенно та же ситуация — предварительное объявление можно сделать только в том пространстве имен, к которому относится класс. Так что все стройно. Разница сводится лишь к тому, что пространство имен можно отрывать и закрывать произвольное количество раз, а с классом так поступать нельзя. Но, насколько я вижу, таких фантази ни у кого и не возникало до сих пор.
Здравствуйте, YuriV, Вы писали:
YV>А она и не является таковой. Здесь вопрос чисто академический — почему не дать такую возможность, если она выглядит логично и не несёт серьёзных трудностей в реализации?
Да со спецификациями доступа грязновато все же получается. Кроме того, если разрешить предварительные объявления вложенных классов за пределами обрамляющих, тогда придется разрешить и предварительные объявления классов за пределами их пространств имен — по точно таким же академическим соображениям. А посколько острой потребности в этих фичах пока не возникало, их отодвигают на задний план, как не особо приоритетные. Но это сугубо мое понимание картины.
хъ
K>Вот один из примеров. Допустим нужно перебрать все элементы кроме первого и последнего:
for (int i = 1; i < v.signed_size() - 1; i++)
{
v[i];
}
K>Со знаковым индексом пример всегда будет корректно работать, с беззнаковым на пустой коллекции ошибка времени выполнения.
Серьезно? Т.е. на знаковых, v[1] на пустом массиве работает благодара особой магии?
В алгоритме, в котором нужно "перебрать все элементы кроме первого и последнего" всегда будет отдельная ветка логики для пустого массива (скорее даже size() < 3), иначе он будет ломаться пусть не на этом конкретном цикле, а где-то еще. А это "всегда будет корректно работать" — тупое заметание мусора под коврик.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Kluev, Вы писали:
K>>Не добавлять новое, а исправлять баги. Не хотят исправлять, пусть честно объявляют вложенные классы deprecated, чтобы программисты не попадались на грабли.
R>ИМХО, невозможность сделать предварительное объявление вложенного класса за пределами обрамляющего — еще не повод объявлять вложенные классы deprecated. Кстати, с обычными невложенными классами совершенно та же ситуация — предварительное объявление можно сделать только в том пространстве имен, к которому относится класс. Так что все стройно. Разница сводится лишь к тому, что пространство имен можно отрывать и закрывать произвольное количество раз, а с классом так поступать нельзя. Но, насколько я вижу, таких фантази ни у кого и не возникало до сих пор.
Чего здесь стройного? Уродство на уродстве и уродством погоняет. Унаследовали из С связку костылей в виде препроцессора и опережающего описания и десятки лет не могут довести до ума. В том же паскале от препроцессора отказались еще в 1978 году. А с++ как обычно. Задержка в развитии на более чем 40 лет.
Здравствуйте, Kluev, Вы писали:
K>Чего здесь стройного? Уродство на уродстве и уродством погоняет. Унаследовали из С связку костылей в виде препроцессора и опережающего описания и десятки лет не могут довести до ума. В том же паскале от препроцессора отказались еще в 1978 году. А с++ как обычно. Задержка в развитии на более чем 40 лет.
Здравствуйте, rg45, Вы писали:
R>Здравствуйте, Kluev, Вы писали:
K>>У нормальных людей от перемены мест слагаемых сумма не меняется.
R>Что-то как-то не в кассу высказывание. В моем варианте тоже не меняется. Не веришь? Смотри:
R>
R> for (size_t i = 1; 1 + i < v.unsigned_size(); ++i)
R> {
R> v[i];
R> }
R>
R>
С знаковыми индексами не нужно думать куда что перенести, не нужно думать при чтении кода, не нужно постоянного микроменеджмента при написание простейших вещей.
С С++ у программистов с одной стороны разжижаются мозги, т.к. в языке все больший упор далается на for each, а с другой стороны в нем исторически заложены грабли в элементных вещах. Я не осуждаю for each вещь крайне нужная и полезная, но и остальные вещи в языке должны быть отшлифованы и обезграблены
Здравствуйте, Patalog, Вы писали:
P>Здравствуйте, night beast, Вы писали:
P>[]
NB>>для знаковых внутрь не зайдет…
P>Ага, точно, спасибо. P>Но, блин, это камень в огород плоскоземельниковзнакоразмерников — люди серьезно считают что это лучше для чтения и понимания?
Если вам не понятен этот код позвольте я первый кину в вас камень
Здравствуйте, PM, Вы писали:
PM>Так в чем загвоздка, подберите упавшее знамя, и вперёд, в комитет, дорабатывать эту важную вещь! Может быть даже РГ21 вам поможет в проталкивании...
А зачем? Мне это не нужно. У Kluev пригорает пусть он и двигает.
PM>А у вас есть такой стратегический план? Было бы любопытно ознакомиться с этим документом.
Концепты, Лямбды, Рефлексия, Модули — в полноценном виде и ещё вчера. Например в С++11/14/17. Сложилось только с лямбда, да и то, внутреннее представление лямбд было известно ещё до С++11 и можно было бы реализовать auto и template лямбды ещё в С++11. И всё это не для того чтобы было, а потому что всё это кардинально изменило бы подход к разработке на С++.
Здравствуйте, night beast, Вы писали:
S>>>* пространства имен не решают ни одной проблемы, а взамен можно использовать префиксы;
K>>Именно так господа. В с++ пространства имен не более чем синтаксический сахар без которого прекрасно можно жить и многие так и делают.
NB>как у вас там, в мире префиксов, adl поживает?
Рискну предположить, что он там не нужен, т. к. он нужен только для неймспейсов. Нет неймспейсов — нет проблем с лукапом параметров. Типы-то самодостаточные получаются.
Здравствуйте, boomer, Вы писали:
B>Рискну предположить, что он там не нужен, т. к. он нужен только для неймспейсов. Нет неймспейсов — нет проблем с лукапом параметров. Типы-то самодостаточные получаются.
это не так. только неймспейсами adl не ограничивается.
оно нужен для обобщенного программирования.
Здравствуйте, night beast, Вы писали:
B>>Рискну предположить, что он там не нужен, т. к. он нужен только для неймспейсов. Нет неймспейсов — нет проблем с лукапом параметров. Типы-то самодостаточные получаются.
NB>это не так. только неймспейсами adl не ограничивается. NB>оно нужен для обобщенного программирования.
Я не защищаю отсутствие неймспейсов. Они действительно удобны и полезны во многих случаях.
Но все же. Представим, что неймспейсов нет, и используются префиксы. В каком случае подадобится ADL для шаблонов?
Здравствуйте, boomer, Вы писали:
B>Я не защищаю отсутствие неймспейсов. Они действительно удобны и полезны во многих случаях. B>Но все же. Представим, что неймспейсов нет, и используются префиксы. В каком случае подадобится ADL для шаблонов?
template<typename T>
void foo(T x, T y)
{
using std::swap;
swap(x, y);
}
Здравствуйте, night beast, Вы писали:
B>>Я не защищаю отсутствие неймспейсов. Они действительно удобны и полезны во многих случаях. B>>Но все же. Представим, что неймспейсов нет, и используются префиксы. В каком случае подадобится ADL для шаблонов?
NB>
NB>template<typename T>
NB>void foo(T x, T y)
NB>{
NB> using std::swap;
NB> swap(x, y);
NB>}
NB>
Представим, что неймспейсов нет, и используются префиксы.
теперь предположите, что у меня в функции foo не стоит using std::swap;
полезете глобальное пространство зачищать?
B>Если же предположить, что должна вызываться функция, переопределенная для типа T — то точно так же. Просто эта функция будет переопределена вот так:
B>
NB>теперь предположите, что у меня в функции foo не стоит using std::swap; NB>полезете глобальное пространство зачищать?
Так оно и так только глобальное.
B>>Если же предположить, что должна вызываться функция, переопределенная для типа T — то точно так же. Просто эта функция будет переопределена вот так:
B>>
Здравствуйте, boomer, Вы писали:
B>Так оно и так только глобальное.
есть две функции
namespace a { struct test {}; }
void foo(T x, T y)
{
using namespace std::swap;
swap(x, y);
}
foo(a::test{}, a::test{});
namespace b { struct test {}; void swap(T, T); }
void bar (T x, T y)
{
swap(x, y);
}
bar(b::test{}, b::test{});
какие определения функции swap у тебя будут в глобальном пространстве имен, чтобы получить похожее поведение?
B>Потому что это не "наша" функция, а переопределение глобальной.
нету никаких "глобальных" есть функции из разных равноправных библиотек.
B>Тогда так:
B>[ccode] B>void swap(company_project_type& x, company_project_type& y) B>{ B> company_project_swap(x, y); B>} B>[/code]
Здравствуйте, Kluev, Вы писали:
K>Именно так господа. В с++ пространства имен не более чем синтаксический сахар без которого прекрасно можно жить и многие так и делают.
Синтаксический сахар очень полезен для мозга: позволяет не заблудиться в дебрях.
K>For example, std::vector wasn't guaranteed to be contiguous, so passing an array to a C library like DirectX could potentially involve creating a temporary copy of it.
По хорошему, вектор не должен быть единым куском, но вот из-за сишников, которые только линейно думать умеют, таки решили сделать vector неотличимым от буфера. И как раз из-за этого приходилось писать свои велосипеды.
S>>* что размеры и индексы могут быть представлены только знаковыми целыми и никак иначе; K>Именно так! Потенциальные грабли нужно устранять, даже ценой двухкратного сокращения диапазона индексов. С++ же спроектирован в погоне за ветряными мельницами, чтобы каждая написанная строка кода давалась программисту кровью и потом. Чтобы вместо того чтобы просто писать работающий код, программист обдумывал бы каждый оператор, не будет ли там смешанной арифметики, переполнения и т.д и т.п.
Здравствуйте, Kluev, Вы писали:
K>С знаковыми индексами не нужно думать куда что перенести, не нужно думать при чтении кода, не нужно постоянного микроменеджмента при написание простейших вещей.
Это не так. Со знаковыми индексами только и думаешь, как не выйти за пределы, ибо то, что за пределами — вообще не известно (было).
Здравствуйте, T4r4sB, Вы писали:
BFE>>По хорошему, вектор не должен быть единым куском, TB>Если он не будет куском, то граблей будет дохрена
Это какие? А то ведь на одной из предыдущих работ был вектор написанный поверх листа кусков памяти — за счёт этого был самый быстрый продукт на рынке.
BFE>>Переполнение знаковых индексов — это ещё хуже. TB>Часто массивы на 2 лярда создаёшь?
Здравствуйте, B0FEE664, Вы писали:
BFE>Это какие? А то ведь на одной из предыдущих работ был вектор написанный поверх листа кусков памяти — за счёт этого был самый быстрый продукт на рынке.
Часто реаллоцируешь?
Я вот два раза в день, не чаще.
BFE>>>Переполнение знаковых индексов — это ещё хуже. TB>>Часто массивы на 2 лярда создаёшь?
BFE>signed char — не signed?
Чарами индексируешься?
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
BFE>>signed char — не signed? TB>Чарами индексируешься?
Если нужно, то — да. А вы как индексы храните? Как 64-х битный указатель?
Здравствуйте, T4r4sB, Вы писали:
BFE>>Если нужно, то — да. TB>Зачем?
Память экономлю.
BFE>>А вы как индексы храните? TB>i32
std::int32_t ?
TB>один раз только не хватило, обошёл
А приложения у вас 32-х битные?
Здравствуйте, B0FEE664, Вы писали:
BFE>По хорошему, вектор не должен быть единым куском, но вот из-за сишников, которые только линейно думать умеют, таки решили сделать vector неотличимым от буфера. И как раз из-за этого приходилось писать свои велосипеды.
Для этого комитету с++ нужно было действовать более конкренто, а не занимать позицию вот вам спецификация, а один там кусок или нет — это детали реализации. Программисту для работы нужен недвусмысленный стандарт без всяких может нет, а может да.
S>>>* что размеры и индексы могут быть представлены только знаковыми целыми и никак иначе; K>>Именно так! Потенциальные грабли нужно устранять, даже ценой двухкратного сокращения диапазона индексов. С++ же спроектирован в погоне за ветряными мельницами, чтобы каждая написанная строка кода давалась программисту кровью и потом. Чтобы вместо того чтобы просто писать работающий код, программист обдумывал бы каждый оператор, не будет ли там смешанной арифметики, переполнения и т.д и т.п.
BFE>Переполнение знаковых индексов — это ещё хуже.
Что значит хуже? В обоих случаях переполнение приведет к ошибочному ходу выполнения программы. Не будете же вы утверждать что при беззнаковом переполнении ошибочное выполнение будет "менее ошибочным".
Но случаев когда переполнение возможно в беззнаковой арифметике однозначно больше.
Здравствуйте, Kluev, Вы писали:
K>Ну получили вы подобное поведение. И что у вас на выходе? Лабиринт из костылей. С введением семантики перемещения такие пируэты вокруг функции свап болше не нужны. Но видимо Ватсон без трубки уже не может.
если кое-кто не в состоянии понять, что это была демонстрация возможностей, то я ничем помочь не могу
[]
K>Если вам не понятен этот код позвольте я первый кину в вас камень
Практически любой код рано или поздно становиться понятен, вопрос лишь в том, сколько времени над ним медитировать.
И да, основное здесь
В алгоритме, в котором нужно "перебрать все элементы кроме первого и последнего" всегда будет отдельная ветка логики для пустого массива (скорее даже size() < 3), иначе он будет ломаться пусть не на этом конкретном цикле, а где-то еще. А это "всегда будет корректно работать" — тупое заметание мусора под коврик.
Здравствуйте, Patalog, Вы писали:++
P>Здравствуйте, Kluev, Вы писали:
P>[]
K>>Если вам не понятен этот код позвольте я первый кину в вас камень
P>Практически любой код рано или поздно становиться понятен, вопрос лишь в том, сколько времени над ним медитировать.
P>И да, основное здесь P>
P>В алгоритме, в котором нужно "перебрать все элементы кроме первого и последнего" всегда будет отдельная ветка логики для пустого массива (скорее даже size() < 3), иначе он будет ломаться пусть не на этом конкретном цикле, а где-то еще. А это "всегда будет корректно работать" — тупое заметание мусора под коврик.
"Всегда будет" — это громкие, но пустые заявления. Вот к примеру простой жизненный пример: итерация пар соседних элементов в массиве для вычисления длинны полилинии
double len = 0;
for (int i = 0; i < points.size() - 1; i++)
len += distance(point[i], point[i + 1]);
return len;
Один универсальный цикл на все случаи жизни. Никакие дополнительные ветки не нужны. В std::С++ такое естественно работать не будет, std-программист либо наступит на грабли, либо будет вынужден погрузиться в микро-менеджмент и "перебрасывать слагаемые"
for (int i = 1; i < points.size(); i++)
На все это тратятся ненужные временные и умственные ресурсы. Особенно смешно выглядят упражнения некоторых товарищей, которые найдя в языке костыль предназначенный для затыкания дыры, устраивают вокруг него пируэты считая это высшим пилотажем программирования.
K> double len = 0;
K> for (int i = 0; i < points.size() - 1; i++)
K> len += distance(point[i], point[i + 1]);
K> return len;
K>
K>Один универсальный цикл на все случаи жизни. Никакие дополнительные ветки не нужны.
Это какой-то тупой пример из области микрооптимизации непонятно чего на уровне ф-и, каноничный пример "микро-менеджмента", против которого ты здесь так ратуешь. Подобный "универсальный цикл на все случаи жизни" в вакууме нахрен никому не нужен, он не имеет собственной ценности. Т.е. где-то сверху это условие все равно будет, например на уровне ГУЯ, чтобы подобная операция была тупо задизейблена, в силу ее идиотизма. А наличие минимум двух точек — будет предусловием ф-и вычисления длины. Более того, в реальном мире, сам по себе инвариант класса полилинии будет состоять в том, что точек минимум две. Иначе ты просто даже создать экземпляр класса не сможешь.
Допускаю, что в каких-то хитрых случаях подобных цикл может иметь право на существование, но на то они и хитрые, зачем выдавать исключение за правило? А в каких-то других случаях — проще будет тупо задвоить точку. Например, в видео часто специально добавляют фиктивные строки слева/сверху блока, чтобы не вводить проверки во внутрь алгоритма обработки.
Здравствуйте, Patalog, Вы писали:
P>Здравствуйте, Kluev, Вы писали:
P>[]
K>>
K>> double len = 0;
K>> for (int i = 0; i < points.size() - 1; i++)
K>> len += distance(point[i], point[i + 1]);
K>> return len;
K>>
K>>Один универсальный цикл на все случаи жизни. Никакие дополнительные ветки не нужны.
P>Это какой-то тупой пример
Покажие острый
P> из области микрооптимизации непонятно чего на уровне ф-и, каноничный пример "микро-менеджмента", против которого ты здесь так ратуешь. Подобный "универсальный цикл на все случаи жизни" в вакууме нахрен никому не нужен, он не имеет собственной ценности.
Это банальный цикл для перебора массива парами соседних значений
P> Т.е. где-то сверху это условие все равно будет, например на уровне ГУЯ, чтобы подобная операция была тупо задизейблена, в силу ее идиотизма.
а если в программе нет ГУЯ?
P>А наличие минимум двух точек — будет предусловием ф-и вычисления длины.
А зачем нужно предусловие? Вы не доверяете математике?
P> Более того, в реальном мире, сам по себе инвариант класса полилинии будет состоять в том, что точек минимум две. Иначе ты просто даже создать экземпляр класса не сможешь.
пока вы говорите о мире выдуманном
P>Допускаю, что в каких-то хитрых случаях подобных цикл может иметь право на существование, но на то они и хитрые, зачем выдавать исключение за правило? А в каких-то других случаях — проще будет тупо задвоить точку. Например, в видео часто специально добавляют фиктивные строки слева/сверху блока, чтобы не вводить проверки во внутрь алгоритма обработки.
Этот цикл не тупой как вы сказали ранее и не хитрый, а вполне очевидный цикл для перебора пар элементов.
Здравствуйте, Patalog, Вы писали:
P>Более того, в реальном мире, сам по себе инвариант класса полилинии будет состоять в том, что точек минимум две. Иначе ты просто даже создать экземпляр класса не сможешь.
В реальном мире полилиния может состоять из одной точки. Например, траектория движения объекта:
1. объект обнаружен на первом кадре, его траектория-полилиния состоит из одной точки;
2. объект обнаружен на втором кадре, его траектория состоит из двух точек;
3. ...
Соответственно, вывод траектории таким вот способом вполне законен. Что тут такого?
Здравствуйте, Kluev, Вы писали:
K>А давайте представим, что земля завтра налетит на небесную ось?
Нет, не представим. Потому что это не имеет отношения к разработке софта.
K>У классов на основе списков и на основе массивов разные сценарии использования, и если требуется то такие в программе живут параллельно, а не переделываются из одного в другой.
Какая наивность. Вы вообще софт, который развивается больше одного месяца, когда-нибудь разрабатывали?
Требования к софту меняются. Профилирование заставляет менять структуры данных в программе. И т.д., и т.п.
K>Это вам потребуется. А мне потребуется написать
K>
K>if (vec.valid_index(i))
K>
K>Я использую свои классы с рациональным набором операций
И что же будет внутри valid_index? Неужели всего одна проверка?
K>Если вы себя официально позиционируете умнее своего собеседника, то вам надо видеть хотя-бы дальше своего носа.
Нет, не умнее. Вероятнее всего просто опытнее.
K>Но в вашем наивном примере, в якобы эффективном переходе от двух сравнений в if(i >= 0 && i < N) к одному в беззнак.арифметике, вы не видите леса за своим носом. Если вы "вычисляете" индекс в беззнаковой арифметике, то чтобы избежать переполнения ваши проверки просто переедут из кода обращения к массиву, в код вычисления индекса.
С чего бы? Это во-первых.
Во-вторых, программисты ошибаются. Поэтому даже в результате вычисления индекса с проверками по ходу вычисления, все равно может получится некорректный индекс. И последним бастионом выступит либо vector::at, либо его аналог.
В-третьих, даже если последовать вашему совету и делать проверки при вычислениях индекса, то там все равно будет две проверки вместо одной.
K>Причем их число будет пропорционально размеру кода.
Еще раз, с чего бы?
K>В знаковой арифметике вы откупаетесь одним простым и эффективным if(i >= 0 && i < N)
Т.е. в вашей вселенной if(i>=0 && i<N) прощее и эффективнее if(i < N)? O_o.
K>Вы — человек действующий шаблонно по указивке комитета, пытаетесь поучать человека действующего осознанно.
А с какого бодуна вы решили, что я действую по указивке комитета? Так уж получилось, что безннаковые числа для размерностей и индексов я начал применять еще до того, как комитет по стандартизации C++ начал работать.
Ну и, в отличии от вас, я не навязываю свою точку зрения. Были бы размерности/индексы знаковыми -- ок, работал бы со знаковыми или использовал бы беззнаковые, там где это нужно. Сейчас они беззнаковые и ОК, меня не парит то, что в чьих-то кодовых базах размерности/индексы знаковые.
Я не заставляю вас перейти от знаковых индексов к беззнаковым. И не пытаюсь доказать вам, что вы неправы в использовании знаковых индексов. И, уж тем более, не называю преверженцев знаковых размерностей/индексов моральными уродами, чье мнение не должно восприниматься всерьез.
Поэтому-то вы "малолетний дебил" (с), который считает, что его инфантильные желания должны быть превыше всего, а его мнение безусловно является самым правильным.
S>Требования к софту меняются. Профилирование заставляет менять структуры данных в программе. И т.д., и т.п.
Не припомню случая когда приходилось бы менять вектор на список и наоборот. Слишком разные сценарии использования. А проектировать софт с учетом возможного столкновения с небесной осью я смысла не вижу.
K>>Но в вашем наивном примере, в якобы эффективном переходе от двух сравнений в if(i >= 0 && i < N) к одному в беззнак.арифметике, вы не видите леса за своим носом. Если вы "вычисляете" индекс в беззнаковой арифметике, то чтобы избежать переполнения ваши проверки просто переедут из кода обращения к массиву, в код вычисления индекса.
S>С чего бы? Это во-первых.
K>>В знаковой арифметике вы откупаетесь одним простым и эффективным if(i >= 0 && i < N)
S>Т.е. в вашей вселенной if(i>=0 && i<N) прощее и эффективнее if(i < N)? O_o.
Имею смелость утверждать. Т.к. реальном мире любая операция минус в беззнаковой арифметике небезопасна и потребует проверки, любая смешанная арифметика небезопасна и потребует проверки. Написание проверок требует дополнительных мысленных усилий и ухудшает читаемость и качество кода. А когда вы эту писанину еще на всякий случай подстрахуете vector::at можете окончательно попрощаться с эффективностью. Отдельно взятый оператор if(i < N) будет эффективней отдельно взятого if(i>=0 && i<N) вот только за ним стоит такой лес граблей, ненужных проверок и ненужных усилий которые сводят на нет всю его мнимую эффективность.
K>>Вы — человек действующий шаблонно по указивке комитета, пытаетесь поучать человека действующего осознанно.
S>А с какого бодуна вы решили, что я действую по указивке комитета? Так уж получилось, что безннаковые числа для размерностей и индексов я начал применять еще до того, как комитет по стандартизации C++ начал работать.
Значит вы с комитетом "нашли" друг друга.
S>Ну и, в отличии от вас, я не навязываю свою точку зрения. Были бы размерности/индексы знаковыми -- ок, работал бы со знаковыми или использовал бы беззнаковые, там где это нужно. Сейчас они беззнаковые и ОК, меня не парит то, что в чьих-то кодовых базах размерности/индексы знаковые.
S>Я не заставляю вас перейти от знаковых индексов к беззнаковым. И не пытаюсь доказать вам, что вы неправы в использовании знаковых индексов. И, уж тем более, не называю преверженцев знаковых размерностей/индексов моральными уродами, чье мнение не должно восприниматься всерьез.
Я не навязываю, а утверждаю очевидные вещи, что в общей практике знаковые индексы имеют больше преимуществ. Чему и следуют большинство языков программирования.
S>Поэтому-то вы "малолетний дебил" (с), который считает, что его инфантильные желания должны быть превыше всего, а его мнение безусловно является самым правильным.
Правильность моего мнения доказывает большинство языков программирования на нашей планете. А ваши оскорбления доказывают лишь только ваш уровень культуры.
хъ
K>Это банальный цикл для перебора массива парами соседних значений
Для перебора пар не нужен знаковый размер.
P>> Т.е. где-то сверху это условие все равно будет, например на уровне ГУЯ, чтобы подобная операция была тупо задизейблена, в силу ее идиотизма. K>а если в программе нет ГУЯ?
Значит будет что-то другое.
P>>А наличие минимум двух точек — будет предусловием ф-и вычисления длины.
K>А зачем нужно предусловие? Вы не доверяете математике?
хъ
N>В реальном мире полилиния может состоять из одной точки. Например, траектория движения объекта: N>1. объект обнаружен на первом кадре, его траектория-полилиния состоит из одной точки;
Вы правы, в реальном мире наверняка бывают программы, которые падают потому-что длина "полилинии из одной точки" рана 0. В этом мире чего только не бывает.
Здравствуйте, Kluev
K>С++ такие пируэты не поддерживает
K>например при смене контейнера с list на vector итератор может стать невалидным (при вставке элемента в теле цикла). И в если случае с индексами вы бы получили ошибку компиляции и смогли бы провести ревизию кода, то с итераторами вы получите ошибку времени выполнения со всеми вытекающими последствиями. Т.е ваши методы гладки только на бумаге, а в реальной жизни гладкостью там и не пахнет. Собственно вся stl и есть бумажная концепция, малопригодная для программирования, для тех кто слаще морковки ничего в жизни не видел.
K>Знаковые на пустом месте не переполняются.
K>Ну а руст это очередной мертворожденный язык. Т.к время каркозябро-ориентированных языков требующих постоянного микроменеджемнта уже прошло.
Простите, но это уже не "малолетний дебилизм", это чистой воды идиотия.
Здравствуйте, Patalog, Вы писали:
P>Вы правы, в реальном мире наверняка бывают программы, которые падают потому-что длина "полилинии из одной точки" рана 0. В этом мире чего только не бывает.
Длина полилинии может быть равна 0 и тогда, когда она состоит из множества точек.
Например, при детекции объект неподвижен и все точки его траектории одинаковые.
Или мы ищем проекцию полилинии с ненулевой длиной на плоскость, а уже на плоскости эта проекция (тоже полилиния) отобразится в точку, но также будет ненулевой длины.
Что ты так прицепился к этому циклу — я не понимаю. Тебя смущает приставка "поли"? Так она не накладывает ограничение снизу, бывают и полиномы нулевой степени.
Здравствуйте, Kluev, Вы писали:
K>Вам пишут очевидные вещи, вы называете их идиотией и сопровождаете оскорблениями. Вы адекватный вообще? Наверное стоит прекратить с вами общение.
Вам дали адекватную оценку ваших заблуждений и очевидного незнания предмета разговора. Но вам проще обвинить собеседника в неадекватности, чем попробовать прокачать собственные знания и кругозор.
По каждому из процитированных мной выше ваших идиотских высказываний можно отдельную статью с кучей примеров написать. Чего, по вполне очевидным причинам, делать не буду.
[]
N>Длина полилинии может быть равна 0 и тогда, когда она состоит из множества точек.
Допустим. Но в этом случае у нас нет полилинии из одной точки или тем более из пустого множества.
N>Например, при детекции объект неподвижен и все точки его траектории одинаковые.
У вас какое-то свое понимание траектории, ибо по определению описывает движение объекта. Но не суть, не будем спорить о терминах.
N>Или мы ищем проекцию полилинии с ненулевой длиной на плоскость, а уже на плоскости эта проекция (тоже полилиния) отобразится в точку, но также будет ненулевой длины. N>Что ты так прицепился к этому циклу — я не понимаю.
Я прицепился? По моему это вы с Клюевым предлагаете этот цикл как икону стиля, дескать как хорошо — не нужны никакие доп. проверки, size() — 1 и ага, а вот с беззнаковыми дескать доп. проверки нужны. И хотя было уже показано, что это не так, т.е. если очень захотеть, то и с беззнаковыми можно обойтись, суть не в этом, позвольте мне еще раз повторить —
В алгоритме, в котором нужно "перебрать все элементы кроме первого и последнего" всегда будет отдельная ветка логики для пустого массива (скорее даже size() < 3), иначе он будет ломаться пусть не на этом конкретном цикле, а где-то еще. А это "всегда будет корректно работать" — тупое заметание мусора под коврик.
N>Тебя смущает приставка "поли"? Так она не накладывает ограничение снизу, бывают и полиномы нулевой степени.
Здравствуйте, Patalog, Вы писали:
P>У вас какое-то свое понимание траектории, ибо по определению описывает движение объекта. Но не суть, не будем спорить о терминах.
Нормальное понимание. Если говорить о видеонаблюдении, но мы наблюдаем проекцию траектории движения объекта на матрице видеокамеры. Движется объект или нет, но его траектория (результаты измерения положения на каждом кадре) может выродаться в одну точку и тогда, когда объект двигается в пространстве, и тогда, когда нет.
P>Я прицепился? По моему это вы с Клюевым предлагаете этот цикл как икону стиля, дескать как хорошо — не нужны никакие доп. проверки, size() — 1 и ага, а вот с беззнаковыми дескать доп. проверки нужны. И хотя было уже показано, что это не так, т.е. если очень захотеть, то и с беззнаковыми можно обойтись, суть не в этом, позвольте мне еще раз повторить - P>
P>В алгоритме, в котором нужно "перебрать все элементы кроме первого и последнего" всегда будет отдельная ветка логики для пустого массива (скорее даже size() < 3), иначе он будет ломаться пусть не на этом конкретном цикле, а где-то еще. А это "всегда будет корректно работать" — тупое заметание мусора под коврик.
Я не считаю этот цикл иконой стиля, но считаю его вполне корректным и понятным, если мы не работаем с беззнаковыми типами. Это не заметание мусора под коврик, в реальности есть случаи, когда надо рисовать на экране линию, которая состоит из одной точки. Лично у меня это было минимум в 3 случаях:
1. При первом обнаружении объекта его траектория состояит из 1 точки и вывод её на экран производился ровно описываемым циклом. Никаких других условий, всё прозрачно и понятно.
2. Когда объект движется, но траектори его оптимизируется и из неё выкидываются точки, чьи координаты во времени не меняются. Что-то типа RLE сжатия — в этом случае траектория может выродиться в одну точку, хотя изначально она имела длину и состояла из большого числа точек.
3. Когда объект трекается в 3D координатах в метрах относительно системы координат в пространстве на поверхности геоида, а потом его траектория проецируется на 2D координатную систему видео в пикселях. Проекция протяжённой в пространстве линии может схлопнуться до одной точки — например, далёкий маленький объект.
И я искренне не понимаю что такого в предложенном цикле: понятен и удобен.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>Вам пишут очевидные вещи, вы называете их идиотией и сопровождаете оскорблениями. Вы адекватный вообще? Наверное стоит прекратить с вами общение.
S>Вам дали адекватную оценку ваших заблуждений и очевидного незнания предмета разговора. Но вам проще обвинить собеседника в неадекватности, чем попробовать прокачать собственные знания и кругозор.
Перечитайте хотя бы собственные сообщения. Где там адекват? Хамство и надуманные, поверхностные примеры. Особенно примечательно ваше предложение писать все в итераторах ради "гибкости", а на самом деле прыгать по граблям перенося ошибки времени компиляции в рантайм.
S>По каждому из процитированных мной выше ваших идиотских высказываний можно отдельную статью с кучей примеров написать. Чего, по вполне очевидным причинам, делать не буду.
Да вы хотя-бы один пример адекватный привели, вместо пусто и сквернословия.
Дальнейший спор на тему что лучше — объект с четко прописанным поведением и инвариантами vs что-то, что может быть точкой, полилинией, проекцией оной на еще что-то, %u-name-it% — считаю бесперспективным.
N>И я искренне не понимаю что такого в предложенном цикле: понятен и удобен.
То, что могут быть случаи когда подобные (в т.ч. и продемонстрированный rg45) могут быть уместны — никто не спорит. Даже пресловутый goto в нек. случаях быть вполне к месту. Но я искренне не понимаю, как подобные примеры могут служить аргументом за использование знаковых целых для индексации и обозначения кол-ва элементов в контейнере.
Здравствуйте, Kluev, Вы писали:
K>Перечитайте хотя бы собственные сообщения. Где там адекват?
Везде. В отличии от. Поскольку:
Можете возразить, что длинно, но до auto stl-юзеры писали километровые std::map<..........., ...........>::const_iterator и не потели. Что касается литералов, то это фантастически бесполезная лабуда. Кто вообще их просил делать это?
...
Если вы не в курсе от раннего stl-мазохизма в продакшене активно отказывались и пересаживались на собственные разработки.
...
на фоне вот этих вопиющих дыр полный бред тратить усилия на такие бесполезные параши как литералы.
...
Самой важной причиной является то, что stl криво спроектированная библиотека. В ней плохо практически все.
...
Эти литералы сделаны в угоду нескольким фрикам, которым не терпелось добавить в stl константы типа в минуте 60 секунд.
просто таки образчики адекватности. И это ведь далеко не все, что вы решили выплеснуть на читателей ваших бредней.
K>Особенно примечательно ваше предложение писать все в итераторах ради "гибкости", а на самом деле прыгать по граблям перенося ошибки времени компиляции в рантайм.
Вы в очередной раз расписываетесь в незнании материала о котором пытаетесь рассуждать.
K>Да вы хотя-бы один пример адекватный привели, вместо пусто и сквернословия.
У вас неоднократно просили пример проблем с отсутствием forward declaration для вложенных классов, но вы так и не смогли (напомню, что ни на один наводящий вопрос по поводу вашего storage и storage::blob-а вы не ответили). А теперь просите, чтобы вам привели пример?
Здравствуйте, Kluev, Вы писали:
K>Смешно слышать такое от человека, который занимается отрицанием реальности. Напомню, что наше общение началось с отрицания вами проблемы опережающего описания вложенных классов.
K>
Так ведь не сломано ничего. Исправлять незачем.
Так вы и не показали проблемы. Раз проблемы нет, то и исправлять нечего.
K>Подписываюсь под каждым словом. Полнейший неадекват тащить в язык сомнительные фичи, превращающие его в помойку, в то время как в языке сотни вопиющих неисправленных проблем.
Не вопрос, раз "малолетний дебил", значит "малолетний дебил", особенно если он сами на этом настаивает.
K>Вот этот код при замене list на vector будет прекрасно компилироваться, но порождать ошибку времен выполнения. Т.е. сценарий когда вы меняете тип контейнера и все "работает" является просто пустым обещанием. В действительности итераторы только ухудшают читаемость и качество кода и создают потенциальные проблемы времени выполнения. Используя родные средства итерирования контейнера (индексы для векторов и указатели для списков) программист вынужден при смене контейнера сделать ревизию кода и исправить потенциальные проблемы.
Это все хорошо, но вот только не имеет отношения к вашему утверждению про "Один универсальный цикл на все случаи жизни."
Если вы забыли, то я вам даже напомню что это за цикл:
double len = 0;
for (int i = 0; i < points.size() - 1; i++)
len += distance(point[i], point[i + 1]);
return len;
Так вот, если бы вы этот цикл написали на итераторах, то было бы без разницы, итерируетесь ли вы по вектору, простому списку, списку чанков, множеству или еще чему-нибудь.
Но поскольку против этого вы, очевидно, ничего возразить не можете, то вы на ходу придумываете другой пример, уже с модификацией контейнера по ходу итерации. Да еще и столь откровенно расписываетесь в незнании STL. Давайте я вам покажу, как этот пример должен был бы выглядеть на STL-ных контейнерах и итераторах (цинк):
std::list/*std::vector*/<int> lst{ 1, 2, 3, 4 };
for(auto it = lst.begin(); it != lst.end(); ++it)
{
if(*it % 2)
{
it = ++lst.insert(it, *it);
}
}
Ну позвольте продемонстрировать вам другие грабли с модификацией вектора, которые будут присутствовать вне зависимости от того, идете вы по вектору посредством итераторов или индексов:
S>>У вас неоднократно просили пример проблем с отсутствием forward declaration для вложенных классов, но вы так и не смогли (напомню, что ни на один наводящий вопрос по поводу вашего storage и storage::blob-а вы не ответили). А теперь просите, чтобы вам привели пример?
K>пример со storage и storage::blob был исчерпывающим, просто вы решили прикинутся шлангом и продолжить отрицание реальности.
Нет. Вам были заданы вопросы, на которые вы отвечать отказались, т.е. слились. Посему незачет. Наличие проблемы вы не показали.
Если вы вдруг захотите ответить, то вот вопросы на которые хотелось бы получить ответы:
Простите, а это пример чего? Почему я должен думать, что все эти описания равноценны? Если вы считаете, что второй вариант является аналогом первого, то вы что-то делаете явно не так и в первом варианте нет смысла вкладывать blob в storage.
и где здесь можно увидеть использование хоть storage, хоть storage::blob вот в этих примерах:
Поскольку здесь использования нет.
S>>Ну, OK. Пример чего вы бы хотели увидеть?
K>Ну вы же там грозились, что можно на мои аргументы статью опровержений написать. Вот и опровергните хотя бы один.
Так ведь ваше незнание материала уже было показано чуть выше. Нужны еще какие-то примеры?
Здравствуйте, Kluev, Вы писали:
BFE>>Переполнение знаковых индексов — это ещё хуже. K>Что значит хуже?
Это значит, что результат переполнения может быть разный в зависимости от компилятора и платформы.
K>В обоих случаях переполнение приведет к ошибочному ходу выполнения программы.
Нет, конечно. На переполнение беззнаковых можно закладываться, а вот на переполнение знаковых — нет.
K>Не будете же вы утверждать что при беззнаковом переполнении ошибочное выполнение будет "менее ошибочным".
Что такое "менее ошибочным"?
K>Но случаев когда переполнение возможно в беззнаковой арифметике однозначно больше.
Конечно случаев больше и поэтому с беззнаковыми переменными программы лучше отлажены, так как выявление ошибки происходит практически сразу, а не через 2147483647 операций.
Здравствуйте, Kluev, Вы писали:
K>В действительности итераторы только ухудшают читаемость и качество кода и создают потенциальные проблемы времени выполнения. Используя родные средства итерирования контейнера (индексы для векторов и указатели для списков) программист вынужден при смене контейнера сделать ревизию кода и исправить потенциальные проблемы.
Итераторы — это идеальная низкоуровневая абстракция, которая позволяет работать с любыми коллекциями без потери эффективности (в отличие например IEnumerable и т.п.). Однако т.к. это низкий уровень, то он должен применяться скорее при написание библиотек и т.п., а в повседневной работе программисту должны быть доступны более удобные абстракции, повыше уровнем. Благо в C++ они теперь есть — это std::ranges. И в таком виде мы получаем краткий, удобный и эффективный код. Что же касается древних итераций по индексу в стиле C... Ну как бы иногда и такое бывает надо (личное мне оно особенно часто в графике встречалось и в матрицах, причём там уже актуальна оптимизация под SIMD и всё такое), но у меня такое ощущение, что некоторые программисты ставят их просто везде от незнания и неумения.
Здравствуйте, alex_public, Вы писали:
_>Что же касается древних итераций по индексу в стиле C... Ну как бы иногда и такое бывает надо (личное мне оно особенно часто в графике встречалось и в матрицах, причём там уже актуальна оптимизация под SIMD и всё такое), но у меня такое ощущение, что некоторые программисты ставят их просто везде от незнания и неумения.
1. А как же одновременная итерация по нескольким массивам? У меня есть такой код, который только на индексах выглядит нормально.
2. Случай итерации по модулю индекса. При рисовании замкнутых фигур или циклическому буферу. Тут есть что-то лучше индекса?
3. Иногда индекс сам по себе несёт семантику, а не просто указывает на позицию элемента в контейнере.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
K>>Смешно слышать такое от человека, который занимается отрицанием реальности. Напомню, что наше общение началось с отрицания вами проблемы опережающего описания вложенных классов.
K>>
Так ведь не сломано ничего. Исправлять незачем.
S>Так вы и не показали проблемы. Раз проблемы нет, то и исправлять нечего.
Эту проблему даже в комитете увидели. Спустя всего 20 лет. Ссылку уже постили http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0289r0.pdf
Чтобы вам проблему увидеть сколько лет потребуется?
K>>Подписываюсь под каждым словом. Полнейший неадекват тащить в язык сомнительные фичи, превращающие его в помойку, в то время как в языке сотни вопиющих неисправленных проблем.
S>Не вопрос, раз "малолетний дебил", значит "малолетний дебил", особенно если он сами на этом настаивает.
Вам видимо очень хочется послушать встречные оскорбления. Помню какое-то время назад здесь за оскорбления активно банили. Жаль сейчас отошли от этой славной традиции.
K>>Вот этот код при замене list на vector будет прекрасно компилироваться, но порождать ошибку времен выполнения. Т.е. сценарий когда вы меняете тип контейнера и все "работает" является просто пустым обещанием. В действительности итераторы только ухудшают читаемость и качество кода и создают потенциальные проблемы времени выполнения. Используя родные средства итерирования контейнера (индексы для векторов и указатели для списков) программист вынужден при смене контейнера сделать ревизию кода и исправить потенциальные проблемы.
S>Это все хорошо, но вот только не имеет отношения к вашему утверждению про "Один универсальный цикл на все случаи жизни." S>Если вы забыли, то я вам даже напомню что это за цикл: S>
double len = 0;
S>for (int i = 0; i < points.size() - 1; i++)
S> len += distance(point[i], point[i + 1]);
S>return len;
S>
S>Так вот, если бы вы этот цикл написали на итераторах, то было бы без разницы, итерируетесь ли вы по вектору, простому списку, списку чанков, множеству или еще чему-нибудь.
Ну хорошо. Этот цикл вы предлагаете писать на итераторах. А другие циклы в программе на чем писать? Вам не кажется что программа в таком случае будет слишком пестрой? Когда мы в одном случае удачно применяем неудачные std концепции, а в другом случае уклоняемся от их потенциальных граблей. Качество кода при таком подходе только ухудшается. Правильно просто не использовать кривые решения. Те кто может себе это позволить так и делают. Вот насколько я знаю в ФБ своя С++ библиотека. Или по вашему там тоже одни малолетние дебилы неосиляторы?
S>Но поскольку против этого вы, очевидно, ничего возразить не можете, то вы на ходу придумываете другой пример, уже с модификацией контейнера по ходу итерации. Да еще и столь откровенно расписываетесь в незнании STL. Давайте я вам покажу, как этот пример должен был бы выглядеть на STL-ных контейнерах и итераторах (цинк): S>
А то что циклы в программе могут быть разными это для вас открытие? Впрочем все что нужно я уже написал в абзаце выше.
S>Ну позвольте продемонстрировать вам другие грабли с модификацией вектора, которые будут присутствовать вне зависимости от того, идете вы по вектору посредством итераторов или индексов: S>
Для вашего примера нужно просто взять знаковый индекс int found_item = -1; и после цикла проверить if (found_item >= 0)
Смотрите как легко становится жить если тип индекса был выбран правильно.
И кстати в этом примере использовать свои любимые итераторы вы не сможете, т.к. итератор тоже будет невалидным.
Вам все равно придется использовать индекс элемента, а т.к. в std он беззнаковый еще и заворачивать его в std::optional
Вот так с кривым stl вы автоматически получаете кривизну на пустом месте.
S>>>У вас неоднократно просили пример проблем с отсутствием forward declaration для вложенных классов, но вы так и не смогли (напомню, что ни на один наводящий вопрос по поводу вашего storage и storage::blob-а вы не ответили). А теперь просите, чтобы вам привели пример?
K>>пример со storage и storage::blob был исчерпывающим, просто вы решили прикинутся шлангом и продолжить отрицание реальности.
S>Нет. Вам были заданы вопросы, на которые вы отвечать отказались, т.е. слились. Посему незачет. Наличие проблемы вы не показали.
Почему-то все участники обсуждения все поняли, в отличии от вас. Так что это ваши проблемы.
S>Если вы вдруг захотите ответить, то вот вопросы на которые хотелось бы получить ответы: S>
Простите, а это пример чего? Почему я должен думать, что все эти описания равноценны? Если вы считаете, что второй вариант является аналогом первого, то вы что-то делаете явно не так и в первом варианте нет смысла вкладывать blob в storage.
S>и где здесь можно увидеть использование хоть storage, хоть storage::blob вот в этих примерах: S>
А это что по вашему? void foo(Storage::Blob *blob); здесь черным по белому используется опережающее описание. Вы извините в шары долбитесь?
S>>>Ну, OK. Пример чего вы бы хотели увидеть?
K>>Ну вы же там грозились, что можно на мои аргументы статью опровержений написать. Вот и опровергните хотя бы один.
S>Так ведь ваше незнание материала уже было показано чуть выше. Нужны еще какие-то примеры?
А вами продемонстрировано непонимание материала. Что гораздо хуже незнания. Что же касается незнания stl то мне нет и нужды знать то, что я не использую и не планирую использовать.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Kluev, Вы писали:
BFE>>>Переполнение знаковых индексов — это ещё хуже. K>>Что значит хуже? BFE>Это значит, что результат переполнения может быть разный в зависимости от компилятора и платформы.
K>>В обоих случаях переполнение приведет к ошибочному ходу выполнения программы. BFE>Нет, конечно. На переполнение беззнаковых можно закладываться, а вот на переполнение знаковых — нет.
С переполнением беззнаковых сложнее работать, т.к. при переполнении у вас будет валидный индекс 0
а со знаковыми вы уйдете в отрицательную область невалидных индексов.
K>>Не будете же вы утверждать что при беззнаковом переполнении ошибочное выполнение будет "менее ошибочным". BFE>Что такое "менее ошибочным"?
K>>Но случаев когда переполнение возможно в беззнаковой арифметике однозначно больше. BFE>Конечно случаев больше и поэтому с беззнаковыми переменными программы лучше отлажены, так как выявление ошибки происходит практически сразу, а не через 2147483647 операций.
а через 4294967296 операций с беззнаковыми что происходит?
Увидели и сказали "да и х с ним". Что как бы говорит, что актуальность этой проблемы, мягко говоря, сильно преувеличена.
K>Чтобы вам проблему увидеть сколько лет потребуется?
Может и пару часов, если вы сможете привести вменяемый пример.
S>>Это все хорошо, но вот только не имеет отношения к вашему утверждению про "Один универсальный цикл на все случаи жизни."
K>Ну хорошо. Этот цикл вы предлагаете писать на итераторах. А другие циклы в программе на чем писать?
Зависит от ситуации, ваш К.О.
Так же ваш К.О. в очередной раз подчеркивает, насколько вы верите в непогрешимость собственного мнения, делая заявления типа "Один универсальный цикл на все случаи жизни." Которые по факту являются выдачей желаемого за действительное, в лучшем случае.
K>Вот насколько я знаю в ФБ своя С++ библиотека. Или по вашему там тоже одни малолетние дебилы неосиляторы?
А вы, когда захотите "малолетнего дебила" найти, лучше в зеркало посмотрите.
K>А то что циклы в программе могут быть разными это для вас открытие?
Вы опять пытаетесь подменить тему. Я нигде не утверждал, что все нужно делать на итераторах. Так что не приписывайте мне свои заблуждения.
K>Впрочем все что нужно я уже написал в абзаце выше.
Главное, что вы написали убогий пример и продемонстрировали незнание STL. А какие глупые слова вы вокруг можете наворачивать уже давно известно.
K>Для вашего примера нужно просто взять знаковый индекс int found_item = -1; и после цикла проверить if (found_item >= 0) K>Смотрите как легко становится жить если тип индекса был выбран правильно.
Для идиотов специально: там дело не в индексах, индексы никак не препятствуют сохранению ссылок на содержимое контейнера. И это глобальная проблема C++, решение для которой сейчас проходит проверку временем в Rust-е.
K>Вам все равно придется использовать индекс элемента, а т.к. в std он беззнаковый еще и заворачивать его в std::optional K>Вот так с кривым stl вы автоматически получаете кривизну на пустом месте.
Вы правда не видите других альтернатив std::optional?
Впрочем, наверняка не видите.
K>>>пример со storage и storage::blob был исчерпывающим, просто вы решили прикинутся шлангом и продолжить отрицание реальности.
S>>Нет. Вам были заданы вопросы, на которые вы отвечать отказались, т.е. слились. Посему незачет. Наличие проблемы вы не показали.
K>Почему-то все участники обсуждения все поняли, в отличии от вас.
Вы не с другими участниками эту тему обсуждали, а со мной. Мне вы не ответили.
K>Так что это ваши проблемы.
У меня нет проблем. Это вы видите проблему с отстутствием forward declaration для вложенных типов. Но продемонстрировать не можете.
K>А это что по вашему? void foo(Storage::Blob *blob); здесь черным по белому используется опережающее описание. Вы извините в шары долбитесь?
Это не использование Storage::Blob. У вас здесь идиома opaque pointer. А в ней этот самый opaque pointer может быть чем угодно. И для opaque pointer вовсе не обязательно показывать пользователю ни класс Storage, ни класс Blob. Можно хоть void* здесь применять, хоть типизированные обертки вокруг void*.
Так что еще раз, где использование Storage::Blob?
K>А вами продемонстрировано непонимание материала.
Если под материалом подразумеваются ваши пируэты с обсуждаемыми темами, то да, следить за ними сложно.
K>Что же касается незнания stl то мне нет и нужды знать то, что я не использую и не планирую использовать.
Т.е. вы признаете, что делаете резкие оценки в адрес того, чего не знаете?
Здравствуйте, so5team, Вы писали:
TB>>По эффективности — без разницы. Любой вменяемый компилятор справится.
S>https://godbolt.org/z/8PqEEE -- что-то у меня выходит разный выхлоп. Может покажете, как получить эквивалентные результаты?
Чёто ужас какой-то(
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, T4r4sB, Вы писали:
BFE>> так как выявление ошибки происходит практически сразу, а не через 2147483647 операций. TB>В паралельной вселенной, где массивы большие-пребольшие...
...думал программист из Microsoft, но коварные производители жестких дисков выпустили сделали 3TB и случился Epic fail. А вообще вот: Как наступить на грабли 32 раза или этапы большого пути.
Наоборот, в реальной вселенной, где массивы маленькие, как только unsigned уходит под ноль программист сразу ловит ошибку. Так что переполнение вниз ловится сразу.
А вот с signed всё работает и тесты проходят..., но много позже, лет через -цать, когда размер файла данных переваливает через два гигабайта, программа начинает сбоить...
Впрочем, верхнее переполнение unsigned приводит к тем же проблемам и почти никто их не отслеживает.
Здравствуйте, so5team, Вы писали:
S>Здравствуйте, Kluev, Вы писали:
S>>>Так вы и не показали проблемы. Раз проблемы нет, то и исправлять нечего.
K>>Эту проблему даже в комитете увидели. Спустя всего 20 лет. Ссылку уже постили http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0289r0.pdf
S>Увидели и сказали "да и х с ним". Что как бы говорит, что актуальность этой проблемы, мягко говоря, сильно преувеличена.
Т.е. баги в языке исправлять ненужно, лучше наплодить побольше фич и побольше новых багов.
K>>Чтобы вам проблему увидеть сколько лет потребуется?
S>Может и пару часов, если вы сможете привести вменяемый пример.
Вменяемость понятие субьективное. Вам была показана невозможность использования опережающего описания вложенного класса. Этого вполне достаточно.
S>>>Это все хорошо, но вот только не имеет отношения к вашему утверждению про "Один универсальный цикл на все случаи жизни."
K>>Ну хорошо. Этот цикл вы предлагаете писать на итераторах. А другие циклы в программе на чем писать?
S>Зависит от ситуации, ваш К.О. S>Так же ваш К.О. в очередной раз подчеркивает, насколько вы верите в непогрешимость собственного мнения, делая заявления типа "Один универсальный цикл на все случаи жизни." Которые по факту являются выдачей желаемого за действительное, в лучшем случае.
K>>Вот насколько я знаю в ФБ своя С++ библиотека. Или по вашему там тоже одни малолетние дебилы неосиляторы?
S>Так они STL не заменяют, а используют: https://github.com/facebook/folly/blob/15f1d999e449fc145f77c3b8a94240981d837d74/folly/experimental/StringKeyedSet.h#L40
В том числе и заменяют. Как минимум классы вектор и стринг.
S>Главное, что вы написали убогий пример и продемонстрировали незнание STL.
Какая трагедия))) Незнание того что тебе не нужно. Что касается примера, то как вы могли сами убедится с list он будет вполне корректно работать. Компилятор не проверяет корректно ли написан stl код. А значит что при написании такого кода весь микроменеджмент ложится на вас. Любой программист может ошибиться в таком коде по невнимательности, а потом поиметь проблемы времени выполнения при переходе на vector. С моей точки зрения это слишком избыточно. Кроме своего кода написать заниматся микроменеджментом от стл и при этом не иметь никаких плюсов и гарантий.
S>Для идиотов специально: там дело не в индексах, индексы никак не препятствуют сохранению ссылок на содержимое контейнера. И это глобальная проблема C++, решение для которой сейчас проходит проверку временем в Rust-е.
Мы сейчас обсуждаем С++ и его проблемы.
K>>Вам все равно придется использовать индекс элемента, а т.к. в std он беззнаковый еще и заворачивать его в std::optional K>>Вот так с кривым stl вы автоматически получаете кривизну на пустом месте.
S>Вы правда не видите других альтернатив std::optional?
Альтернатив множество вплоть до вызова use_item прямо в теле цикла, разделение циклов на два и т.п. Я не телепат чтобы угадывать какую именно альтернативы вы выбрали.
S>Впрочем, наверняка не видите.
K>>>>пример со storage и storage::blob был исчерпывающим, просто вы решили прикинутся шлангом и продолжить отрицание реальности.
S>>>Нет. Вам были заданы вопросы, на которые вы отвечать отказались, т.е. слились. Посему незачет. Наличие проблемы вы не показали.
K>>Почему-то все участники обсуждения все поняли, в отличии от вас.
S>Вы не с другими участниками эту тему обсуждали, а со мной. Мне вы не ответили.
Не ответил потому что посчитал их не существенными. Баг языка был показан однозначно. А на демагогию у меня времени нет.
K>>Так что это ваши проблемы.
S>У меня нет проблем. Это вы видите проблему с отстутствием forward declaration для вложенных типов. Но продемонстрировать не можете.
K>>А это что по вашему? void foo(Storage::Blob *blob); здесь черным по белому используется опережающее описание. Вы извините в шары долбитесь?
S>Это не использование Storage::Blob. У вас здесь идиома opaque pointer. А в ней этот самый opaque pointer может быть чем угодно. И для opaque pointer вовсе не обязательно показывать пользователю ни класс Storage, ни класс Blob. Можно хоть void* здесь применять, хоть типизированные обертки вокруг void*.
S>Так что еще раз, где использование Storage::Blob?
Pointer declarator: the declaration S* D; declares D as a pointer to the type determined by decl-specifier-seq S.
Storage::Blob это тот самый тип который используется в Pointer declaration, и которым мы не можем воспользоватся из-за недостаточной поддержки опережающего описания вложенных классов.
K>>А вами продемонстрировано непонимание материала.
S>Если под материалом подразумеваются ваши пируэты с обсуждаемыми темами, то да, следить за ними сложно.
K>>Что же касается незнания stl то мне нет и нужды знать то, что я не использую и не планирую использовать.
S>Т.е. вы признаете, что делаете резкие оценки в адрес того, чего не знаете?
Знаю достаточно чтобы не использовать. Запаха и вида вполне достаточно.
BFE>А вот с signed всё работает и тесты проходят..., но много позже, лет через -цать, когда размер файла данных переваливает через два гигабайта, программа начинает сбоить... BFE>Впрочем, верхнее переполнение unsigned приводит к тем же проблемам и почти никто их не отслеживает.
Здравствуйте, T4r4sB, Вы писали:
BFE>>То, что с беззнаковыми ошибки встречаются два раза реже? Да, удалось. TB>В 10 раз чаще. Продавливание под 0 будет случаться постоянно, приводя к трудноуловимым последствиям.
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, T4r4sB, Вы писали:
BFE>>>То, что с беззнаковыми ошибки встречаются два раза реже? Да, удалось. TB>>В 10 раз чаще. Продавливание под 0 будет случаться постоянно, приводя к трудноуловимым последствиям.
BFE>Почему трудноуловимым?
Ну потому что где и почему формула выдала число 10005000 вместо -1 — не всегда очевидно.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Здравствуйте, Шахтер, Вы писали:
Ш>Комитет по стандартизации пора расстрелять. Такое ощущение, что эти дебилы никогда не писали софт сложнее hello world.
Они как раз писали. И понимают, что код в первую очередь нужно читать и уже во вторую — писать.
Здравствуйте, Kluev, Вы писали:
K>программист может сам себе гарантировать, в платформозависимом решении.
Увы, нет. Все может накрыться медным тазом просто после обновления компилятора.
K>а если вы думаете что ваши программы будут выполнятся вечно на всех новых платформах и новом железе, то я вас расстрою. еще при нашей жизни от них и эха не останется.
Вечно -- нет, конечно же. Но если у вашего кода время жизни не превышает месяца, то не нужно думать, что так у всех. В моем багаже есть проекты, которые стартовали с моим участием и развиваются затем лет 10, а некоторые и больше 15. И не считая чужого кода, который временами попадает на сопровождение.
K>А где реально нужны пространства имен? Приведите хоть один реальный случай случая когда нельзя было бы обойтись префиксами. Новшества вводят для удобства, а не только когда реально нужно. Кроме того forward declaration для вложенных классов это тот случай когда исправлять реально нужно, потому что это баг на уровне языка.
Интересно наблюдать за тем, как люди, сильно покалеченные программированием на Си и С++, называют багом языка то, что костыль для исправления настоящих багов языка не достаточно хорош.
Так вот, баг на уровне языка, это необходимость в forward declaration. Были бы нормальные модули, не нужно было бы этим заморачиваться. Надеюсь современный С++ придет к модулям рано или поздно. Он все больше и больше начинает быть похож на нормальный язык программирования без заморочек. Пусть комитету и потребовалось больше десяти лет, чтобы мы могли писать std::vector<std::pair<int, int>> вместо std::vector<std::pair<int, int> >.
Здравствуйте, Kluev, Вы писали:
K>И по вашему в том числе. Нотацию с префиксами вы сами забраковали постами выше, ну а класс storage в пространстве имен storage и комментариев не требует.
То-есть ты сам написал хрень с пространством имен storage и классом storage и теперь утверждаешь что это проблема языка? Кто мешает выбирать нормальные имена и нормально структурировать свой код? Отсутствие forward declaration для вложенных классов или отсутствие мозгов?
S>А теперь представим, что в процессе сопровождения и оптимизации у вас points из вектора превратился в простой список или список чанков. И у вас больше нет индекса, зато есть итераторы, которые позволяют вам итерироваться по новому контейнеру последовательно.
представил вычислительную геометрию на std::list и
Здравствуйте, T4r4sB, Вы писали:
BFE>>Почему трудноуловимым? TB>Ну потому что где и почему формула выдала число 10005000 вместо -1 — не всегда очевидно.
Это бывает только если мешать в выражениях знаковые и беззнаковые — во всех остальных случаях всё очевидно.