Как стать автором
Обновить

Комментарии 427

а концепты попадут в стандарт только в виде required clause (1) или варианты 2/3 тоже «доедут»?
// 1
template <typename T>
    requires Copyable<T>()
void foo(T x);
// 2
template <Copyable T>
void foo(T x);
// 3
void foo(Copyable x);


А есть ли возможность сделать перегрузки constexpr/runtime для функций? Отсутствие этой фичи не позволяет считать на этапе компиляции многие математические функции, в т.ч. exp/log.

Какой статус у Ranges?
Required clause (1) вошли и будут в C++20.
Варианты 2 и 3 активно обсуждаются и полируются, в них есть проблемы:
  • Вариант 2 не позволяет работать с концептами принимающими сразу два шаблонных параметра
  • Вариант 3 вызывает недоумение в случае
    void foo(Copyable x, Copyable н);
    Типы у переменных x и y должны быть одинаковые или нет?


А есть ли возможность сделать перегрузки constexpr/runtime для функций?

Идёт работа над волшебной функцией is_constant_evalueated(). Она позволит внутри функции делать ветвление, в зависимости от того, выполняется функция на рантайме или на этапе компиляции:
    constexpr double power(double b, int x) {
      if (std::is_constant_evaluated() && x >= 0) {
        // A constant-evaluation context: Use a
	// constexpr-friendly algorithm.
        double r = 1.0, p = b;
        unsigned u = (unsigned)x;
        while (u != 0) {
          if (u & 1) r *= p;
          u /= 2;
          p *= p;
        }
        return r;
      } else {
        // Let the code generator figure it out.
        return std::pow(b, (double)x);
      }
    }


Какой статус у Ranges?

Идёт активная работа по принятию из в C++20. Есть все шансы на успех.
Вариант 2 не позволяет работать с концептами принимающими сразу два шаблонных параметра

это критично с точки зрения РГ даже с учетом того, что для этого есть fallback синтаксис?
Типы у переменных x и y должны быть одинаковые или нет?

(мне) очевидно, что нет. Неужели это является решающим фактором?
Полностью разделяю ваше мнение! Но в комитете много людей, и у них свои задачи и требования к фичам языка.

Кому-то не нравится вариант 3, так как из сигнатуры функции не понятно что это шаблонная функция (нужно знать, что Copyable — это концепт; проблем не возникает в случае со стандартными концептами, однако для больших кодовых баз со множеством своих концептов разобраться будет намного сложнее).

Кому-то не нравится вариант 2, потому что он громоздкий :)

Про модули и сопрограммы что-то известно? Herb Sutter даёт прогноз, что сопрограммы скорее всего войдут, а насчёт модулей нет ясности.

По модулям будет отдельная встреча этим летом. Будут обсуждать только модули.

Буквально 2 заседания назад появилось новое предложение по модулям, позволяющее экспортировать макросы и упрощающее миграцию старого кода на модули. На ближайших заседаниях будут пытаться слепить старые и новые предложения в одно. Общее предложение скорее всего будет сначала выкачено в эксперимент (в виде обновленного Modules TS), и только после этого смержено в стандарт. В общем, шансы увидеть модули в C++20 есть, но они не велики.

Сопрограммы скорее всего войдут в C++20. Были попытки выдвинуть другое (конкурирующее) предложение по сопрограммам. Поддержки новый подход не получил. Если новых предложений или возражений не поступит, то Coroutines TS окажется в C++20.
Что мешает просто договориться, что модули и макросы несовместимы? Ведь все равно с приходом модулей придется библиотеки переписывать в какой-то степени, почему бы «под шумок» не выкинуть оттуда макросы, заменив на всякую constexpr-магию? И волки сыты и овцы целы.
Потому что многих людей не устраивает, что придётся код перелопачивать сильно на новые модули. Поэтому и придумывают, как бы так безболезненно заменить хедеры на модули с оставшимися экспортированными макросами, так как есть много кода, который ну очень сильно завязан на макросы.
многих людей не устраивает, что придётся код перелопачивать сильно на новые модули

Помню как Дельфи помер, когда очередная новая версия оказалась потерявшей совместимость со старым кодом.
Это текущий Modules TS (модули в первоначальном виде).

Ряду компаний очень не понравилось отсутствие макросов и, как следствие, невозможность «модуляризировать» системные заголовочные файлы.
а то, что макросы плюют на namespace и чужой код, а также в разы более убогие, чем constexpr, ряду компаний нравится?
Хочу напомнить, что некоторые вещи без макросов в С++ по-прежнему нельзя реализовать.
Или я просто не знаю, как, но что-то сомневаюсь.
НЛО прилетело и опубликовало эту надпись здесь
И для рефлексии в том числе, но не только. Например, макрос, который я назвал EXEC_ON_SCOPE_EXIT, принимающий лямбду и создающий на стеке объект, выполняющий эту лямбду в деструкторе. Тонкость в автоматическом именовании этого объекта, чтобы включал номер строки (что гарантирует уникальность, если не пихать по два в строку):

#define EXEC_ON_SCOPE_EXIT auto CONCAT_EXPANDED_ARGUMENTS_2(scope_exit_executor_, __LINE__) = detail::makeOnScopeExitExecutor


В общем случае, макросы, использующие стрингификацию и/или конкатенацию строк, обычно решают задачи, не решаемые средствами С++.
НЛО прилетело и опубликовало эту надпись здесь
зато код на меня не кричит

Вы имеете в виду upper case? Можно же переименовать :)
То, что вы предлагаете, функционально тождественно, но много лишних символов, я от такого люблю избавлять программиста.
reflexpr

Это что-то, чего мы ждём в С++20? Очень мало результатов в Гугле по этому термину.
НЛО прилетело и опубликовало эту надпись здесь
всё жду, когда это полноценно имплементируют в основных компиляторах:
en.cppreference.com/w/cpp/experimental/source_location
Пока есть только в gcc
Например, constexpr преобразование указателей. Что-то типа:
static constexpr volatile uint32_t* MY_PTR = (volatile uint32_t*)0x12345678;
А без этого невозможен никакой embedded и низкоуровневое системное программирование. Приходится всё только на многоуровневых извращённых макросах делать.
Колоссальный косяк, кстати, который не позволяет писать под железо на полноценных плюсах. А всё потому, что бородатые дядьки опять заигрались в стандарты.
Тогда просто не будут переходить на модули те, у кого макросы в апи. Тот же gtest/gmock, например.
В текущем виде да. Или они там могут просто дождаться модулей+рефлекшн и переписать свои фреймворки на тот же подход, который используют C#, Java и прочие. Понятно что переписывать никто ничего не хочет, но это цена прогресса.
Вот и получается, что либо ждем лет 10-15 всех необходимых фич, либо поддерживаем макросы в модулях и делаем быстрый и безболезненный переход.
И практически не получаем выигрыша в производительности :)
А вот тут хочется подробностей, полагаю, что авторы Modules TS и ATOM должны были проводить какие-то эксперименты на своих кодовых базах.

Я читал про эксперимент на модулях от clang (а авторы proposal наверняка вдохновлялись и такими модулями), они давали прирост 60% (или 10% по сравнению с использованием precompiled headers).

Хочется еще узнать, а как реализованы Modules TS и ATOM в gcc. Используют ли они предложенное Страуструпом бинарное представление пропарсенного C++ кода? Или у них какое-то свое представление? И таскают ли в реализации ATOM текстовую копию кода для поддержки экспорта макросов?
Работать 10 лет и получить прирост скорости компиляции на 10% больший чем дают precompiled headers — это провал. Люди работающие над clang — одни из авторов ATOM. Можно приблизительно представить, какой прирост производительности с подходом из ATOM можно получить.

Один из разработчиков Modules TS утверждает, что макросы — одна из основных причин тормозов. Поэтому пока вы не начнёте использовать модели без макросов — довольствуйтесь 10% прироста скорости.

Лично мне ATOM нравится простотой внедрения в большие кодовые базы, и не нравится своим небольшим приростом скорости компиляции.

Modules TS и ATOM в gcc сделаны и информация об актуальном состоянии есть вот тут gcc.gnu.org/wiki/cxx-modules
Вот поэтому и хочется узнать о результатах экспериментов от разрабов Modules TS. Что-то вроде: «Вот мы сделали модули без макросов и компиляция ускорилась в 10 раз, а сделали с макросами — получили прирост в 0,1».
Может подход в духе precompiled headers и достигает теоретического предела в приросте?

Я ни в коем случае не защищаю макросы и не пишу своих в кодовой базе. Я заинтересован в том, чтобы разработчики библиотек активно переходили на модули, но как бы не получилось так, что будем еще 10 лет разрабатывать модули, а потом 10 лет переходить на них.
Такое ощущение будто вы хотите одним седалищем усесться на два стула. Чтобы и модули были, и легаси не пришлось переписывать. Так, скорее всего, уже не получится. Если в модулях будут макросы, польза от их введения будет весьма условной.
Лично я не жду от модулей в языке с открытой внешней компоновкой никакой пользы кроме вреда. Яву уже превратили в породистую корову, несущую несколько дорогих разукрашенных стампидных седел. Пришла очередь C++?
Что это за зверь такой «открытая внешняя компоновка»? C++ единственный язык который до сих пор не имеет концепции модулей, которая даже старше ООП и появилась с изобретением процедурного и структурного программирования. Чтобы использовать библиотеки в C++ нужно как в С лезть на низкий уровень и заниматься флагами компилятора, служебными макросами (#ifdef/#endif), включением исходных файлов (в C это оправдано, поскольку язык предназначен для системного программирования и прекрасно для этого подходит). Еще «лучше», т.н. header-only библиотеки, которые часто используют еще и шаблоны что приводит к непомерному дублированию кода, ведь полная оптимизация возможно только в полностью функциональном языке, но никак не в императивном.
Простите за это очевидное объяснение, но хочется избежать недопонимания.
Возможно, моя русская терминология неточна: она формировалась в 90 годы прошлого века во время чтения сделанных издательством «Мир» переводов классических англоязычных руководств по C и С++. Имеется в виду тот факт, что язык C++ работает с отдельными единицами компиляции, превращая их в объектные файлы определенного для целевой платформы формата (с функциями и глобальными переменными). Этот формат, соглашения о вызовах и ABI, устройство выполнимых бинарных образов и разделяемых библиотек, строго говоря, к языку C++ не относится, а относится к целевой платформе и в основных чертах остается неизменными со времени изобретения ассемблера. В частности, часть платформы — компоновщик, перебирает указанные ему объектные файлы, смотрит, на какие имена внешних объектов они ссылаются и найденные объекты (тела функций и определения глобальных переменных) как-то платформозависимо укладывает в выполнимый файл. Если компоновщик не найдет нужный объект — будет ошибка времени компоновки.
Противоположностью этому являются варианты явной компоновки, когда компилятор формирует бинарные файлы не только со скомпилированным кодом, но и с мета-информацией о видимых снаружи именах. Такие файлы и называются (обычно) модулями. В единице компиляции требуется указывать не только имя внешней сущности (функции или переменной), но и то, из какого модуля ее следует брать. В этом случае компоновщик не ищет первое попавшееся имя, а ищет конкретный объект в конкретном модуле, что и быстрее, и «типобезопаснее». Примеры — Turbo Pascal и Modula2, C#, можно продолжить.
Совместимость с C и используемый в C (взятый из экосистемы ассемблера) инструментарий — совершенно сознательное решение Страуструпа, сделанное при создании C++. По моему мнению, это решение сыграло важнейшую роль в том взрывном распространении C++, которое мы наблюдали в 90 годы XX столетия))).
И мне не очень понятно, где тут место для сколь-нибудь развитой системы модулей. Опасаюсь, что в результате такого «скрещивания ужа с ежом» получится нечто, что будет смотреться столь же органично, как седло на корове или пятая нога у собаки. Впрочем, это мое личное мнение и я его никому не навязываю.
Информация о символах есть всегда. В тех же объектных файлах, или как вы себе представляете работу компоновщика? То что сам язык об этом не знает, это большой минус языка. С другой стороны, если язык ограничен в ресурсах, а C был системным языком для ограниченных в ресурсах платформ, то поэтому делегирование такого знания компоновщику было элегантным решением. Но для C++ это — тяжелое наследие детства с «игрушками прибитыми к полу» минимальной рудиментарной системой модулей (те же объектные файлы и т.н. «библиотеки» — архивы объектных файлов).
С чем именно это сравнивалось? Наиболее тормозной вещью в сборке С++-кода является раздельная компиляция. Дефолтная ситуация выглядит так: есть один cpp-файл на 1к строк, в него инклюдится 100500 хедоров на 1кк строк, тем самым каждый файл раздувается до 1к1к строк.

Насколько я понимаю, в модулях единицей трансляции является не файл, а множество файлов — модули. Это, скорее всего, и даёт весь профит. И это нужно учитывать при сравнении.

Верно. Распишу поподробнее:

Когда вы собираете проект, каждый cpp файл может компилироваться параллельно (это хорошо, отличная масштабируемость).

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

Ещё одна проблема — невероятно количество макросов (они пораждаются например include guards). Держать их всех в памяти и препроцессировать документ становится тяжёлой задачей.

Модуль — это набор файлов, собранных воедино и сохранённых на диск в понятном для компилятора бинарном виде. Таким образом, при подключении модуля, компилятор просто считает его с диска в свои внутренние структуры данных (минуя этапы открытия нескольких файлов, парсинга, препроцессинга и некоторых других вспомогательных вещей).

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

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

И наконец, финальная стадия сборки проекта — линковка. В данный момент линковщик много времени тратит на выкидывание одинаковых блоков скомпилированного кода (вы подключили <string> 100 раз — линкер выкинет 99 скомпилированных std::string). С модулями линкеру не придется этим заниматься, т.к. файл модуля не будет вкомпиливаться внутрь собранного cpp файла.

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

Когда-то пытался измерить — всегда получал очень малый вклад этих стадий во время компиляции.

Но при этом НЕ ускоряется стадия оптимизации вашего кода. Если большую чать времени компилятор оптимизирует вашу программу — большого ускорения компиляции не ждите

Оно одновременно и замедляет и ускоряет. Замедляет за счёт того, что происходит более глобальный ipo, а ускоряет за счёт того, что не нужно 10раз оптимизировать одни и те же функции в контексте того же header-only, которого в С++ предостаточно.

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

Макросы так же засирают глобальный неймспейс.

Если модули позволят перевести весь легаси-код в модули из которых не будут торчать сишные кишки, макросы и тому подобное — это будет прекрасно. Для чего же они современному коду, особенно если использовать модные/набирающие популярность техники, я не понимаю.
Все еще не понятно, действительно ли модули смогут значительно ускорить сборку по сравнению с unity билдами. Не очень похоже, что препроцессниг макросов занимает значительное время.

И сразу открытый вопрос: а почему нельзя совместить оба подхода, с экспортом макросов и без? Даже если модуль с макросами будет собираться дольше, пусть это будет опцией при сборке модуля. Если опция не включена, то и хранить модуль можно в более оптимальном виде, и знать можно, что он не повляет на последующие текстовые инклюды. Дескать, если разработчик настолько сильно желает экспортировать макросы в своем апи, что готов пожертвовать временем компиляции у конечных потребителей — пусть. Пользователям решать, использовать такую библиотеку или нет.
Юнити билды становится адово использовать в случае локальной разработки. Скажи разработчику что каждый инкрементный билд будет по полминуты занимать (вместо 1-2 секунд) — он криво на тебя посмотрит.
Да и на сервере, не так чтобы сильно ускоряется сборка. Я делал такую штуку — в cmake делал автоматическое объединение cpp всей цели для одной либы. Ускорение — не больше, чем в два раза. И плюс мы получаем тьму неудобств от необходимости следить за анонимными неймспейсами и т.п.
Если еще и локально одна схема, а на билде другая — это вообще адъ.

Пока лично для меня самая эффективная схема — распределенная сборка) Железо докупить оказывается дешевле. Когда сборка параллелится на 100+ ядер — ускорение налицо. Понятно, что и там есть ограничение сверху (возможность параллелить, возможности сети), но зато эффектом можно пользоваться и на CI, и на дев машине.

Я пока раздумываю как в свою систему распределённой сборки модули прикручивать. Получается, что по сети не только единицу трансляции гонять придется, но и все используемые скомпиленные модули.
У меня коллеги ускорили сборку своего проекта с 15 до 5 минут с помощью unity билдов. И думаю, что скорость инкреметного билда их не сильно разражает, т.к. большую часть этого времени все равно занимает линковка пачки статических зависимостей.

Распределенную сборку они тоже пробовали — не взлетело, слишком медленно. Полагаю, что уперлись в wifi сетку.

Но мой поинт в другом. Модули по своей сути могут отчасти напоминать идею unity билдов. Предобработать исходники, объединить их в удобном виде и закешировать — и последующая компиляция будет быстрой.
Нет, я с вами не соглашусь, модули это идея противоположная юнити билдам) Я бы скорее его выразил как «каждый хедер- прекомпилируемый».
Офисную сеть для разработчиков делать целиком на вайфае — омг) Ну у нас есть те кто с ноутбуков компилят, ускорение все равно значительное.

«скорость инкрементного билда их не раздражает» — какие спокойные разработчики! Лично меня цикл сборка-запуск больше 5 секунд начинает заметно напрягать, а 15 — откровенно раздражать.

Модули еще по идее и линковку должны ускорять нехило, т.к. не будет определений одного и того же в каждой оттранслированной единице.
Я думаю идеальный вариант для меня через пять лет — модули + распределённая сборка.

Ну и компоновка всего проекта как кучи статичных либ — вообще сомнительное удовольствие)

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

Ах да, еще замечательное — т.к. все файлы идут вместе, начинает теряться необходимый набор хедеров в каждой единице трансляции. Начинаются вещи вроде «убрали один cpp файл — все отвалилось», а файл этот может исключаться из сборки какой-то опцией, т.е. нужно тестировать все комбинации опций при вообще любой правке, даже не в хедерах.
В общем, в плане поддержки это очень тяжело. От распределённой сборки все же треба только железо/сеть, ты никак не думаешь о каком-то специфичном коде.
Детали эксперимента можно тут посмотерть: reddit. Это всего лишь локальный эксперимент какого-то разработчика, но все же лучше, чем ничего.

Если рассуждать о скорости компиляции, то модули подступаются к этому вопросу с нескольких сторон.

Например в случае, если не экспортим макросы, то единицей модуля может быть единица трансляции после фаз трансляции 1-7(8), представленная в оптимальном бинарном виде. Согласитесь, если вам вместо файла с исходниками дадут вот такую единицу модуля — компилироваться все в итоговый файл будет быстрее.

Или, например, объявление модуля. Не знаю, как там после последней встречи объединили Modules TS и ATOM, но конкретно от ATOM ранее было предложение разрешать объявление модуля только на верху единицы трансляции. Это позволит компилятору прочесть только заголовки файлов и построить граф зависимостей между файлами, чтобы потом оптимальнее подгружать их при компиляции.

Другой момент касается шаринга явных и неявных инстанцирований шаблонов: в модулях их стараются расшаривать по-максимому, чтобы не делать повторно одни и те же инстанцирования. Я правда не знаю, как современные компиляторы работают с инстанцированиями — пытаются ли запоминать, что какой-то шаблон уже обрабатывали и инстанцировали в другой единице трансляции? Если нет, то здесь модули так же дадут ускорение, т.к. это одно из главных вкладов во время компиляции.
НЛО прилетело и опубликовало эту надпись здесь

Zapcc делает именно это — кэширует инстанциации между ТУ. Для этого они держат в памяти сервер с кэшем.

НЛО прилетело и опубликовало эту надпись здесь
Из того как работает zapcc, я так понимаю, модули его не сильно и ускорят, он и так каждый файл препроцессированным держит? Можно интересно считать, что то ускорение, которое дает zapcc- оценка сверху для ускорения от модулей?
Согласитесь, если вам вместо файла с исходниками дадут вот такую единицу модуля — компилироваться все в итоговый файл будет быстрее.

Это даёт свои проблемы. Мы потеряем то самое преимущество, особенно в контексте header-only, когда мы всегда можем увидеть как минимум сигнатуры функций. Очень сомневаюсь, что модули дадут указанный выше побочный эффект.

Выше я уже писал, что не получал особого профита от тех же pch. Может на обычных инклюдах с одними декларациями это и даёт что-то, но это уже давно не модно.

Опять же, один из тех же профитов, который даёт header-only — простую кросскомпиляцию и между платформами и между компиляторами. Дадут ли тоже самое модули? Сомневаюсь.

Если нет, то здесь модули так же дадут ускорение, т.к. это одно из главных вкладов во время компиляции.

Поэтому совместно с шаблонами используется header-only подход.

Мы потеряем то самое преимущество, особенно в контексте header-only, когда мы всегда можем увидеть как минимум сигнатуры функций.

Не совсем понял. Под «увидеть» понимается посмотреть на код в human-readable формате? Если да, то вопрос тулчейна, он должен научиться показывать интерфейс модуля в читаемом виде, все необходимое для этого в модуле есть.

Опять же, один из тех же профитов, который даёт header-only — простую кросскомпиляцию и между платформами и между компиляторами. Дадут ли тоже самое модули? Сомневаюсь.

Какая связь между кроссплатформенностью и header-only? Как в header-only спокойно можно писать непереносимый код, так и не в header-only можно писать кроссплатформенно. Это ортогональные понятия.
Если да, то вопрос тулчейна

И текущие реализации модулей это умеют? Как это должно быть реализовано? В ситуации с хедерами всё понятно — я открыл файл и прочитал( в самом примитивном случае). Что же будет делать тулчейн? Создавать файлы, которые будут эмулировать хедеры, перекладывать это на шею ide?

Какая связь между кроссплатформенностью и header-only?

Прямая.

Как в header-only спокойно можно писать непереносимый код, так и не в header-only можно писать кроссплатформенно.

Дело не в этом. Нельзя просто так взять и собрать одну часть одним, а другую часть вторым компилятором. Т.е. бинари теряют вообще какой-то смысл по части дистрибуции, надо будет опять всё собирать.

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

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

Далее, дистрибуция. Это опять приключения. Нужна статическая линковка, либо приключения с контейнерами. Статическая линкова сама по себе то ещё приключение и мало кто её поддерживает из зависимостей.

В случае же с header-only нет никаких проблем с дистрибуцией самих зависимостей — просто носишь собой/забираешь из vcs. Нет никаких проблем со сборкой — нет никакой сборки вообще. Нет никаких проблем с дальнейшей дистрибуцией бинарей — нет никаких бинарные зависимостей, линковки и прочих приключений

Создавать файлы, которые будут эмулировать хедеры, перекладывать это на шею ide?

Почему бы и нет? Либо просто показывать интерфейс в менюшке автокомплита, как это делается во многих ide сейчас?

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

Далее, дистрибуция. Это опять приключения. Нужна статическая линковка, либо приключения с контейнерами.

Если думать о дистрибуции бинарного представления модулей, то беспокоиться нужно будет только о том, чтобы бинари модулей-зависимостей были от того же / совместимого компилятора. Пляски с линковкой отпадают.

Если и о компиляторах думать не хочется, можно распространять только исходники и собирать их самостоятельно в модули, в любом случае соберутся быстрее старого подхода. header-only библиотека ортогональна простоте сборки: у неё точно так же могут быть зависимости, которые потребуется собрать, у неё могут особые требования на флаги компиляции, которые желательно носить рядом, в том же cmake. Хорошие header-only либы этими проблемами не страдают, ну так и модули можно писать точно так же, избегая сложных зависимостей и сложной сборки.
Почему бы и нет? Либо просто показывать интерфейс в менюшке автокомплита, как это делается во многих ide сейчас?

Интерфейс мало кому нужен, к тому же было проигнорировано множество тезисов, как и множество деталей.

В подсказке описание типа/класса тоже можно показать? Да и сигнатуру функции, особенно с какими-то концептами, контрактами и прочим. Где это всё показывать? И в каком виде? В виде кода?

Опять же, куда девать коменты — нужно ещё и это эмулировать.

Так же, я говорил не только о сигнатурах, но и о самих исходниках, которые всегда и удобно доступны в ситуации использования header-only.

Если думать о дистрибуции бинарного представления модулей, то беспокоиться нужно будет только о том, чтобы бинари модулей-зависимостей были от того же / совместимого компилятора.

Проблема в том, что в ситуации с header-only думать не нужно. И пока это лишь фантазии, а я сравнивал реальность. Я утверждал, что модули дают профит по части кросскомпиляции и задавал вопрос, а дадут ли тот же профит модули? Я не сравнивал модули и header-only. Был вероломно подменён тезис, что очень некрасиво.

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

Про старый подход я и не говорил. В контексте же правильного header-only не существует всех тех проблем, которые и дают модулям какой-то профит.

header-only библиотека ортогональна простоте сборки

Header-only предполагает header-only, и это очевидно. Если header-only тянет какие-то левые бинарные зависимости — это уже не header-only.

у неё точно так же могут быть зависимости, которые потребуется собрать

Header-only зависимости не нужно собирать.

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

Флаги компиляции чего? У меня такое чувство, что вы мало знакомы с темой, очень мало. Header-only это встраиваемая зависимость, она не собирается — она собирается в контексте вашего кода. Для неё не может быть каких-то отдельных флагов для cmake — они будут накладываться на всё то, куда вы это заинклюдили. И если это «куда» является так же header-only, то инклюдится это ТОЛЬКО в ОДНО место, а значит флаги всегда ОДНИ.

К тому же, у стандартного кода может быть только один флаг — это std, который совместим сверху вниз, а значит в любом случае код использующий header-only зависимость нужно собирать с std не ниже необходимого для зависимости.

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

Модули — это уже лишние телодвижения. При этом уже нужна какая-то система сборки, уже нужно будет делать всё тоже, что и
при header-only, только с куда большим набором заморочек. При этом просто в голословное «можно» я поверить не могу.

Модули для леги кода? Да. Модули для блобов? Да. Преимущества очевидны, а вот в сравнение с современными техниками — преимущества очень не очевидны, по крайней мере мне.
У меня такое чувство, что вы мало знакомы с темой, очень мало.

Может, не стоит скатываться в обвинения о непрофессионализме? Это оскорбительно и лишь провоцирует на взаимные обвинения.


Давайте лучше почитаем proposals по модулям и предположим, как эти предложения смогут реализовать компиляторы. А для начала договоримся об одном понимании header-only библиотек, какие "гарантии" они дают, а какие — нет.


К тому же, у стандартного кода может быть только один флаг — это std, который совместим сверху вниз, а значит в любом случае код использующий header-only зависимость нужно собирать с std не ниже необходимого для зависимости.

Предположим, я пишу проект на последнем C++17 и подключаю к нему header-only библиотеку, которая:


  • Использует в своей реализации старенький std::bind1st. Эта вещь была удалена в 17 плюсах. Gcc спокойно скомпилирует заинклюженную в мои cpp файлы эту header-only библиотеку. Clang тоже. Но только если будет использоваться std либа от gcc. Если я подключу std от clang, то получу ошибку — там эта вещь была удалена в соответствии со стандартом. Флаг std не совместим сверху вниз, в нашем примере он навязывается проекту от header-only либы, иначе проект не соберется только из-за несборки кода header-only библиотеки.
  • Использует чуть более современный std::thread. Чтобы мой проект собрался с этой header-only либой на линуксе, я должен слинковаться с pthread.
  • Использует std::filesystem. Тогда на компиляторе gcc я должен слинковаться с stdc++fs.
    Вывод: header-only библиотека может зависеть от бинарей даже в случае, если используется только стандартный c++.

А теперь о том, какие же "гарантии" дает header-only либа. А она гарантирует лишь:


  • что все необходимые файлы с реализацией будут автоматически подключены в конечный cpp файл;
  • если какая-то часть библиотеки не используется в конечных cpp файлах, она туда не подключается и соответственно не собирается, ускоряя сборку;

А так же гарантирует минусы:


  • включая в себя все необходимые файлы с реализацией, соответствующий заголовок при включении в конечные cpp файлы будут требовать разбора/инстанцирования/компиляции одного и того же кода раз за разом в каждом cpp файле.
  • Сделает видимым конечному потребителю все детали реализации, давая возможность заиспользовать то, что не должно быть использовано напрямую.

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


И почему вообще header-only библиотеки вы называете "современным" подходом? Что в этом современного? Его разве изобрели пару лет назад?


Неужели эти "гарантии" не смогут предоставить модули?
Способ поиска модуля при импорте — implementation defined. Компилятор точно так же может сделать директиву, где будет принимать директорию для поиска подключаемых модулей.
В случае, если будет принято предложение ATOM об объявлении модуля только на верху файла, тогда компилятору будет достаточно прочесть заголовки всех файлов в этой директории, чтобы понять, что потребует сборки. Это не так быстро, как чтение хедера по прямому пути из инклюда, но выполняется однократно, в отличии от многократного чтения хедера при каждом включении. Если предложении от ATOM не будет принято, компилятору придется прочесть/распарсить каждый файл целиком, чтобы найти там объявления модуля. Это соответственно дольше.
Всё! Гарантии header-only либы могут быть соблюдены и модулями! При этом они лишены недостатоков header-only либы — вся внутренняя реализация библиотеки не будет видна конечному коду и будет компилироваться только один раз.


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

Использует в своей реализации старенький std::bind1st. Эта вещь была удалена в 17 плюсах. Gcc спокойно скомпилирует заинклюженную в мои cpp файлы эту header-only библиотеку. Clang тоже. Но только если будет использоваться std либа от gcc. Если я подключу std от clang, то получу ошибку — там эта вещь была удалена в соответствии со стандартом. Флаг std не совместим сверху вниз, в нашем примере он навязывается проекту от header-only либы, иначе проект не соберется только из-за несборки кода header-only библиотеки.

Вы утверждали, что нужны какие-то флаги(отдельные) отдельно для header-only, на что я вам ответил — никаких отдельных флагов нет, а всё, что может наложить header-only на ваш код — это std.

Опять же, что из текста выше должно следовать? То, что вы взяли библиотеку, которая несовместима с вашим компилятором? Ну дак это никакого отношения к теме не имеет. Аналогичное будет в любом другом случае.

По поводу «навязывается» — я уже об этом говорил, в любом случае он навязывается.

По поводу совместимости — оно всё совместимо, а ссылаться на 1-2 исключения имеет мало смысла, которые, к тому же, мало кто использовал и которые выпиливаются банальным реплейсом.

Использует чуть более современный std::thread. Чтобы мой проект собрался с этой header-only либой на линуксе, я должен слинковаться с pthread.

Будь она какой угодно — вам нужно будет линковаться с pthread.

Вывод: header-only библиотека может зависеть от бинарей даже в случае, если используется только стандартный c++.

Очевидно, что стандартные зависимости мало кого волнуют, ведь они стандартные. О них никто и не говорил, их никто не учитывает. Если что-то требует с++17 — обеспечьте это. -pthread, -lstdc++fs — это всё заморочки конкретного компилятора/платформы.

К тому же, я всё это заранее проговаривал:

Если header-only тянет какие-то левые бинарные зависимости — это уже не header-only.

Я уточнял и про левые зависимости, и про то, что header-only может их тянуть, и про то, что я не считаю подобное header-only.

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

Это не проблема, организуйте нормальную(модульную) сборку. К тому же, ничего не мешает организовать в проекте подобное и без сборки. Разделите проект на header-only модули. Он будет работать и собираться быстрее.

У такого подхода есть одна проблема — компилятор не сможет собрать модуль в сто миллионов строк кода, но подобная проблема будет и в самих модулей в случае, если единицей трансляции является модуль.

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

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

Это просто придирки. Таких проблем ни у кого нет, а если кому-то нужно что-то заиспользовать — он заиспользует это и реализация «отдельно» ему никак не помешает.

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

Такая же придирка, как и в случае выше. Простой пример /usr/include? Инклюды обладают очень простым свойством — их можно накидать куда угодно и использовать, язык это умеет.

И если что-то и нужно передавать — это корневой каталог по типу /usr/include и не более того. И даже если это какая-то сложная иерархия, то они организуется из любого thrid_payty без каких-либо проблем.

В сравнении с тем, что нужно сделать в ситуации со сборкой — это 1 против 100.

И почему вообще header-only библиотеки вы называете «современным» подходом? Что в этом современного? Его разве изобрели пару лет назад?

Изобрели их дано, массовым явление стало достаточно недавно.

В современных реалиях «старый» подход оправдан очень в малом кол-ве случаев. И в противовес старому подходу я называю header-only новым подходом.

Неужели эти «гарантии» не смогут предоставить модули?
Способ поиска модуля при импорте — implementation defined.

Если бы они сделали инкрементальную сборку, то это да — даст очень большой профит. Что ещё даст какой-то профит — я не знаю.

В случае, если будет принято предложение ATOM об объявлении модуля только на верху файла, тогда компилятору будет достаточно прочесть заголовки всех файлов в этой директории, чтобы понять, что потребует сборки. Это не так быстро, как чтение хедера по прямому пути из инклюда, но выполняется однократно, в отличии от многократного чтения хедера при каждом включении.

Меня не особо радуют всякие ограничения про «вверху файла». К тому же, одно дело «может», а другое дело «делает».

Всё! Гарантии header-only либы могут быть соблюдены и модулями! При этом они лишены недостатоков header-only либы — вся внутренняя реализация библиотеки не будет видна конечному коду и будет компилироваться только один раз.

Очень сомнительно, что компилятор сможет взять точку входа(файл) и построить все модули без костылей. Потребуется система сборка, что уже минус.

Опять же, «внутренняя реализация видна» — для меня является не минусом, а плюсом. Никакого минуса я тут не вижу вообще.

По поводу «компилироваться» — это недостаток по части оптимизации. Это будет очередная линковка. Если же это не линковка, то компиляция будет, а модуль будет просто частично скомпилирован( и то, лишь в теории).

Видимо, мы друг друга не убедим до тех пор, пока не увидим, как implementation defined детали работы с модулями будут реализованы в компиляторах.
Хм, мне всегда казалось, что компоновка в этом аспекте не уступает компиляции, а часто компиляцию превосходит. Нет?
Или у них появятся форки, в которых макросы заменены на constexpr силами людей, у которых ещё есть шило в одном месте…
В конце концов, столько времени потратить на то, чтобы минимизировать влияние препроцессора на время компиляции, и опять мы суём макросы, чтобы увеличить влияние препроцессора на время компиляции… зачем?
Модулей нет, зато есть куча всякого ада. А еще нет вирутальной шаблонной функции. Просто браво…
Ну это кому как. Я контракты второй год с нетерпением жду, а std::bit_cast люди хотели ещё лет 20 назад…

Ну и не стоит так надеяться на модули, в 10 раз они компиляцию не ускорят (в ближайшее время).
Ускорят. Просто надо дать время компиляторописателям, чтобы они это написали. А так… пока в Стандарт не приняли, некуда и спешить.
Ускорят.
Боюсь, будет сильно зависеть от кода. По опыту работы с некоторыми header-only библиотеками получается, что иногда львиная доля времени во время компиляции уходит на инстанцирование и оптимизацию шаблонов, а не на загрузку и обработку заголовочных файлов.
Modules TS предлагает по-максимому расшаривать explicit и implict инстанцирования, идущие с модулем.
Контракты — это очень хорошие новости. Я правильно понимаю, что для них ещё нет имплементации ни в gcc ни в clang ни вообще нигде, даже прототипа?
Увы, пока нет. Но в контрактах очень заинтересованы крупные компании, скорее всего имплементация появятся в скором времени.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Offtop: кстати, девушка с видео есть на фотке из поста
Offtop^2: главный нелюбитель фоток (Бьярни) спрятался за мной, пока я фоткал фотографа.
Логика подсказывает, что если у нас есть constexpr std::regex значит у нас есть «сделай из строки что угодно на этапе компиляции», т.е. фактически те же макросы что в языке D. Это конечно породит большой поток ненависти от некоторых, но мне очень даже нравится, т.к. намного проще инжектировать прямо в компилятор строки нежели пытаться использовать API самого компилятора, строить там ООП структуры через специальный API, все такое. Это, если хотите, «метапрограммирование для чайников».
Ждём настоящего «нормального» метапрограммирования с приходом Reflection в язык. Вот тогда уже можно будет делать очень много интересных вещей (а если ещё и скрестить с металкассами...)
Вангую что с метаклассами мы получим:
* генерацию парсеров из EBNF и других форматов описания грамматик
* ORM классов из коробки
* сигнал/слоты Qt без макросов
* расцвет DSL
* красивый RPC
* ???
сигнал/слоты Qt без макросов

github.com/woboq/verdigris
У автора в блоге (https://woboq.com/blog/), кстати, много всего интересного написано про нестандартное использование C++.
Но ведь по ссылке с макросами… :(
Да, точно. Имел ввиду, что без MOC.
А про сами метаклассы что-нибудь слышно, кстати?
Метаклассы базируются на рефлексии, рефлексия требует constexpr контейнеров и алгоритмов.

Constexpr алгоритмы мы дотолкали до стандарта. Надеемся увидеть в C++20 constexpr контейнеры; рефлексию — в C++23. Где-то в это время и появятся метаклассы в стандарте.
Спасибо!
Надеюсь, доживем :)
НЛО прилетело и опубликовало эту надпись здесь
Парсеры на шаблонах: github.com/taocpp/PEGTL
В принципе почти хватает и сейчас, без метапрограммирования
constexpr!
Я вместо if(!result) пишу if (result == false), ибо восклицательный знак легко теряется из виду.
Может стоит дать другое имя?
И будут ли весь math модуль делать constexpr? Мне бы не помешал constexpr синус и косинус.
Да и может быть стоило бы всё-таки сделать какой-нибудь «std2»?
А какое имя вы предлагаете?
да даже и не знаю. Возможно, какой-нибудь static_expr или compilet. Сходу так не скажешь. Но наличие восклицательного знака однозначно напрягает. В C++ нет ни одного ключевого слова с восклицательным знаком. Зачем нарушать эту тенденцию?

Ещё одно занятное изменение, которое рассматривается для приёма в C++20 — это constexpr! функции.

Я когда прочитал это предложение, то не понял в тот же миг, что оно говорит о чем-то новом)
Я вообще когда только начал знакомиться с constexpr, был крайне раздосадован, что они как раз не ведут себя «всегда constexpr!»., если бы можно было вернуть время вспять, я бы предложил constexpr и maybe_constexpr какой-нибудь (соответствующий сегодняшему)
абсолютно с вами согласен
Поддерживаю, делать настолько похожие ключевые слова — не лучшая идея.
Я уж молчу про то, как легко слово «констекспр» произносится вслух -_-' Но говорить вслух «констекспр!» будет вообще невозможно.
«Констекспрбанг»? «Констэкспр экскламейшн марк»? «Констэкспр восклицательный знак»?

Гуглить тоже очень тяжело будет.
Вы правы. Закиньте идею на stdcpp.ru, чтобы она не потерялась. Я автору предложения передам ваши возражения, думаю он прислушается
А можно ссылку на оригинальный пропозал или на существующее обсуждение? А то я уже ничего нагуглить не могу -_-'
В вашем примере восклицательный знак «зажат» между скобкой и идентификатором, от чего плохо читается (например, я бы предпочел такое условие обособить). За обсуждаемой конструкцией почти всегда будет следовать пробел.
И всё-таки, насчёт библиотеки: constexpr(2011), концепты, метаклассы, модули. Чем не повод сделать абсолютно новую и чистую либу, которой будет легко и приятно пользоваться, которая не будет страдать от миллиона проблем?
Это всё мне напоминает чемодан, который с каждым годом становится всё дырявее и дырявее, а его выкинуть жалко, поэтому дырки латают и красят новым модным цветом.
Да все контейнеры (также их итераторы) и алгоритмы будут гораздо проще и выразительнее с концептами и с учётом существования compile-time выражений почти всё можно переписать и сделать чище.
При этом всём не нужно выкидывать старую библиотеку (дабы всеми необходимая обратная совместимость осталась). Но и развивать старую библиотеку я не вижу смысла.
Такой потенциал теряем…
А что бы вы хотели такого сделать в стандартной библиотеке, что поломает обратную совместимость? Концепты и контракты можно добавлять к уже имеющимся классам стандартной библиотеки, и всё будет OK.
Всё. Нужно позволить себе провести тотальный рефакторинг, с учётом появления супер-плюшек, появившихся за последние 16 лет и не бояться потерять обратную совместимость. Со спокойной душой пересмотреть большинство концепций и сделать библиотеку изначально заложив туда свежий фундамент, а не достраивать этажи поверх старого и не прочного фундамента.
Я понимаю, что я как-то сегодня прилично так умничаю, но просто мне кажется, что для молодых специалистов (как и я) был бы C++ более привлекателен с подобной новой и чистой библиотекой.
Недавно в теме по std::visit происходили серьёзные стычки между сообществом C++ и сообществом Rust. Аргументы Rust-овщиков были вполне убедительными, поскольку Rust — это молодой язык, который создавался опираясь на горький опыт своих предшественников.
А тут такой шанс по новому взглянуть на мир в пределах плюсов, с новыми возможностями и не заменять старую библиотеку и не приклеивать новые возможности к старым с помощью скотча, а сделать всё сразу и хорошо.
Ну ведь сейчас так и происходит, что все новые фичи прикручивают к старым. Тот же constexpr почти по всей библиотеке можно прилепить. Но это ведь в корне может поменять все концепции библиотеки.
Концепты, модули и метаклассы — это через чур глобальные изменения для того, чтобы быть использованными поверх старых наработок. Необходимо использовать сей потенциал. Иначе, всё-равно все станут писать свои велосипеды. Так и происходит сейчас даже. constexpr std::swap мне приходилось писать свой, абсолютно такой же, но с constexpr. Вы продвигаете constexpr std::regex. Контейнеров новые штуки также касаются. Итераторы будут безумно изящнее с концептами. Подобных примеров уже существует уйма. Библиотека std простаивает.
Мне кажется, если молодому специалисту объяснить, что «безопасное» подмножество C++ — это то, что соответствует Core C++ Guidelines, а все остальное не рекомендовано и должно быть инкапсулировано, ему станет гораздо легче жить. А огромное количество старых вещей в Core C++ Guidelines запрещены или разрешены лишь для короткого списка исключений.

Да, такой безопасности, как в Rust, не будет. Но будет гораздо лучше, чем раньше.
О, я вас узнал сразу)
Но я же говорю не о безопасности, а обо всей библиотеке в целом. Да её можно сделать хоть смешав с GSL.
Факт в том, что на базе новых новшеств и базируясь на том, что язык за последние 20 лет тотально прокачался, нужно пересмотреть стандартную библиотеку вдоль и поперек. А старую оставить доживать ради обратной совместимости и всё.
Если сейчас посмотреть предложения на stdcpp.ru, то там большая часть предложений начинается со словосочетания «добавить constexpr к ...». Появляются модули, концепты и метаклассы. Это приведет к чему? К тому же самому, что происходит с constexpr. При этом модифицируя существующие сущности, которые уже много раз итак модифицировались и базировались совсем на других вещах, комитет получает головную боль, поскольку нужно все сделать аккуратно и нигде ничего не сломать и не переименовать и т.д. и т.п.
Также, что-то теряет свой смысл и со временем выбрасывается. Но это всё вытекает в то, что библиотека растянет на долгие годы (ибо стандарт выходит раз в 3 года) своё эволюционирование и в итоге придёт к тому же самому, что можно сделать здесь и сейчас и в разы проще.
Есть история с Python3, которая пугает всех в комитете.

Если мы сделаем std2, то как заставить пользователей на него быстро переехать? Если переезжать долго, то придётся десяток лет развивать две версии стандартной библиотеки, получать лучи ненависти от людей, вынужденных мигрировать на новую версию библиотеки…

А главное — в чём плюсы то? Пока что, всё что хочется, все новые фишки, можно добавлять к стандартной библиотеке не ломая обратную совместимость.
Если мы сделаем std2, то как заставить пользователей на него быстро переехать? Если переезжать долго, то придётся десяток лет развивать две версии стандартной библиотеки, получать лучи ненависти от людей, вынужденных мигрировать на новую версию библиотеки…

Комитет ведь что-то сподвигло сделать C++ Core Guidelines и GSL.
И я подразумеваю то, что развитие старой библиотеки прекращается. Новая в себя будет включать идентичные сущности, но без мусора, в адекватном и чистом виде.
Я не настаиваю на том, что я абсолютно прав и нужно сделать так как я говорю) Не мне решать.

А главное — в чём плюсы то? Пока что, всё что хочется, все новые фишки, можно добавлять к стандартной библиотеке не меняя обратную совместимость.

Как по мне, «пока что» — это до C++20. Уж слишком масштабное обновление будет.
Согласитесь, что constexpr уже сместил сильно с места стандартную библиотеку, о чём я выше написал.
Я вижу библиотеку сейчас, как фундамент, который не был изначально рассчитан на тот груз, который на нём стоит. И со временем любое строение изнашивается и становиться более хрупким, тем-более если сверху достроить пару этажей и дополнительные балкончики, а также кондиционеры навешать)
Аналогии почти всегда неверны. Если сейчас поломать либу, то никто на неё просто не будет переходить и получится разделение как с Python 2/3, только С++ before 20 и C++ 20 и выше. Такое себе, лично я считаю.
Ну вот как раз сейчас любой желающий может сделать такую библиотеку для себя, смешав с GSL по вкусу, поэтому проблема не сказать, чтобы была очень острой, на мой взгляд. А второго Python3 нам не надо.
Странно записывать std::visit во что-то древнее, ему ведь всего 1 годик :)

Так что конкретно вы хотите изменить в стандартной библиотеке? Какие основы хотите пересмотреть?
Странно записывать std::visit во что-то древнее, ему ведь всего 1 годик :)

Там весь конфликт был не вокруг std::visit, а вокруг того, что Rust-овщики пришли прогонять C++ сообщество со своими правильными умными указателями)
Кто же спорит — указатели в Rust самые правильные!

Жаль только что пользоваться ими не удобно, оттого и серьёзных програм на нём нет.</troll-mode>
Я не буду с вами спорить и я сам тремя руками за C++.
Просто в том споре мы знатно присели, оправдывая себя «обратной совместимостью» и возрастом.
Уж слишком убедительные и настырные противники были.
Но я вот совсем не планирую уходить на Rust, поскольку душа у меня к плюсам тянется.
Также я не требую «такие плюшки как в Rust». Я сейчас о другом говорил всё время. О том, что уже есть, но под новым углом.
Пусть растоманы пишут что хотят, вам то какая разница? Каждый выбирает средство сам. Не хотят растоманы поддерживать тонны уже написанного кода и написать с нуля? Пожалуйста, кто ж против.
Вот я же не первый, кто пишет об «std2». Это периодически мелькает перед глазами:
вот
и
вот
и я искренне надеялся на то, что так и будет с C++20.
Вы ведь и сами желайте всё то, что есть модифицировать, но с учётом обратной совместимости вам это обходиться сложнее, чем могло быть. Мне кажется, что с 20-ым стандартом всё станет еще в пять раз сложнее.
Назревает новая эпоха, а библиотека Modern C++ всё еще не Modern.
Я видел на ютубе видео с конференции, где поднимали тему std2, нужна ли она, в каком виде, но названия видео не вспомню. Нашел только презентацию от одного из участников той дискуссии: www.youtube.com/watch?v=fjtwfauk7a8.
Да. Абсолютно тот же мотив.
Да, я там был. И могу рассказать о настроениях в зале — скептическое.
Очень надеюсь, что такой ломающей совместимости никогда не будет в Стандартной библиотеке. И в любом треде, где это будет подниматься, я буду топить исключительно против.
никто и не говорит о том, что нужно выбросить нахрен существующую библиотеку. Говорится о новой библиотеке, которая будет эдаким ремэйком старой, но с учётом новшеств последних 10-ти лет, коих предостаточно.
Вам не кажется, что внедрение концептов, метаклассов, контрактов, constexpr-выражений в текущую библиотеку не станет более пагубным действием и слишком размазанным по следующему десятилетию?
Суть в том, что будет абсолютно свежий код, который станет более поворотливым.
Что предлагают сейчас:
constexpr std::regex
Переименовать все новые *_ref функции и классы в *_view
algorithm который можно использовать в constexpr
std::complex который можно использовать в constexpr
Убедить международный комитет не дублировать все контейнеры стандартной библиотеки
Constexpr для std::char_traits и std::string_view
constexpr для begin/end/reverse_iterator/move_iterator и базовых методов array
std::allocate_unique

Наверняка где-то простое добавление constexpr к сигнатуре функции невозможно в связи с текущей реализацией. Далее следует цепная реакция. В итоге придётся перелопатить чуть-ли не всё, что есть. Чем это лучше?
Что вы выберете, сделать эко-жигуль, впихнув в старый эко-двигатель или сделать нормальный и современный эко-мобиль и далее уже плясать вокруг него?
Или вам нравится, когда требования к тем же контейнерам выражаются письменно где-то здесь? Это хотя-бы концептами поправят…
Говорится о новой библиотеке, которая будет эдаким ремэйком старой, но с учётом новшеств последних 10-ти лет, коих предостаточно.
Для этого не нужен комитет по стандартизации. Есть пример boost. Если найдётся достаточно заинтересованных людей, которые готовы будут написать эту библиотеку — мы все только рады.
Нет, там конфликт был из-за того, что один Rust-оман, плохо знающий C++, подумал, что unique_ptr и shared_ptr используются в C++ для тех же целей, для чего родные ссылки в Rust-е. И пришлось потратить кучу времени, чтобы понять это :(

Ну а так, конечно, std::visit и std::variant по сравнению с полноценным паттерн-матчингом и алгебраическими типами данных выглядит скромненько. Только вот в обозримом времени АлгТД в C++ вряд ли завезут. Если бы завезли, то в C++ было бы проще переиспользовать полезные практики из других современных языков.
ИМХО, проще тогда уже сделать новый язык, который по синтаксису, идеологии и каким-то основным приемам будет настолько сильно напоминать C++, что при желании можно будет брать имеющийся C++ный код, править его на 20-30% и получать код на новом, более современном, удобном и безопасном языке. Заодно можно было бы в приказном порядке закрыть проблемы с отсутствием единой системы сборки и общей системы управления зависимостями.

Ценность же самого C++ в том, что сохраняется совместимость с древним кодом, который написали и отладили давным-давно, но который все еще работает. У меня самого были в практике случаи, когда доставался старый код, написанный и заброшенный к тому времени уже лет 8 как, просто компилировался новым компилятором и шел в дело. Или когда старый код, который эволюционировал около 10 лет в рамках C++98 за пару вечеров был переведен под C++11. Потребовалось в ряде мест поменять std::auto_ptr на std::unique_ptr и еще что-то по мелочи. Или когда узнаешь, что где-то работает твой код, который был написан еще году в 2008-ом, и в котором были переиспользованы куски кода, написанного в 1998-ом.
ИМХО, проще тогда уже сделать новый язык, который по синтаксису, идеологии и каким-то основным приемам будет настолько сильно напоминать C++

Не соглашусь и уже далеко не одна подобная попытка была.
Стоит всё-таки разделить язык и его стандартную библиотеку.
Сам язык позволяет написать новую «идеальную» библиотеку, так что нет необходимости делать новый тысячный ЯП.
Все ключевые изменения 20-ого стандарта относятся строго к языку, а не к библиотеке, в том то и дело. И всё то, о чём я здесь так много писал, относиться только к библиотеке.
Не соглашусь и уже далеко не одна подобная попытка была.
А вот я не помню ни одной заметной попытки, где хотели бы оставить синтаксис и идеологию максимально близкой к C++.

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

В Rust-е и синтаксис другой, и borrow-checker с lifetimes заставляют по другому думать. И объектная модель совсем другая. Так что переделать C++ный код в Rust — это даже больше, чем переписать, тут еще и перепроектировать потребуется.

Что еще?
Открыл для себя наличие ключевых слов not, or, and в C++ и забыл о крипто-синтаксисе !, &&, ||, хотя последние два еще читаемые, но вот тоненький восклицательный знак почти незаметен. В новом коде самое то.
НЛО прилетело и опубликовало эту надпись здесь
Пока что, любой side effect является Undefined Behavior. Скорее всего так и останется.
НЛО прилетело и опубликовало эту надпись здесь
вам о возможном нарушении контракта скажет компилятор еще на этапе сборки.
НЛО прилетело и опубликовало эту надпись здесь
контракты — механизм для уменьшения числа проверок в рантайме к минимуму (плюс бонусом дополнение к документации). Вы предлагаете разменять доп. быстродействие на вывод в консоль? На мой взгляд, это мало чем лучше ассертов.
НЛО прилетело и опубликовало эту надпись здесь
Ну вы почитайте дальше, в секциях 2 и 3 подробно описано что это за «build system setting»: вы собираете в одном из режимов: «без runtime проверок», либо «только дешевые проверки» и «все проверки». Первое предназначено для релизных сборок, а второе и третье — отладочных

Я имел в виду с++ контракты. Впрочем, они полностью подходят под общепринятое понятие контракта.
НЛО прилетело и опубликовало эту надпись здесь
Не делать их :)
НЛО прилетело и опубликовало эту надпись здесь
Там во многих местах при работе контрактов нарочно поставлены UB.

В данный момент у комитета нет «лучших практик» по использованию контрактов, поэтому все скользкие места помечены как UB. Разные компиляторы сделают флаги под эти скользкие места. Пользователи языка наберутся практики по использованию контрактов, и тогда станет понятно, на что именно заменить то или иное UB.

А до тех пор, комитет решил выпустить контракты в минимальном виде. Виде, который подходит для использования в стандартной библиотеке и для использования в кодовых базах ряда крупных компаний.
НЛО прилетело и опубликовало эту надпись здесь
т.е. на данный момент контракты — это просто doxygen-friendly assert и ничего более?
А кто будет гарантировать, что тело контракта — это pure function? C++ компиляторы такое осилят?
НЛО прилетело и опубликовало эту надпись здесь
Именно, я хотел сказать, что «не делать их» — это плохой совет т.к. нет возможности гарантировать их отсутствие, следовательно рассчитывать на то, что сайд-эффектов не будет — очень ненадёжно. Это практически гарантирует UB время от времени т.к. человек не может не делать ошибок, а тут их сделать очень легко, а найти — может быть очень трудно.
НЛО прилетело и опубликовало эту надпись здесь
Ну более error-prone механизм не припомню. Обычно UB можно избежать следуя довольно простым правилам.
компиляторы времен царя гороха поддерживают аттрибуты типа pure/const
const — это не pure. Какой C++ компилятор поддерживает pure?
они позволяют объявить что-то pure, но я не вижу, что бы компилятор мог вывести pure для функции.
float twice(float x) __attribute__ ((pure)) 
{ return x*2.0f;}
float fourtimes(float y) 
{ return twice(twice(y));}

Компилятор не узнает, что fourtimes — pure.
GCC должен уметь такое выводить. Попробуйте перепроверить, где-то на уровне IR должна выставиться инфа о том что функция pure.
тогда почему purity не вводится в стандарт вместе с контрактами и не требуется для контрактов, а вместо этого нарушение purity объявляется как UB?
Разные компиляторы умеют выводить эти атрибуты в разной степени. Думаю вы не будете рады, если у вас код с контрактами соберётся на одном компиляторе, а на другом будет говорить «error, not pure»
именно, потому нет способов гарантировать отсутствие side effects, но приходится требовать его, что точно приведёт к UB, т.к. для человека гарантировать отсутствие side effects на практике нереально, слишком нетривиальная задача.
Узнает, причём знает без всяких pure. Не будет он знать только тогда, когда у него не будет доступа к телу функции.
Он может узнать, но гарантий нет, их нет в стандарте. Стандарт не требует от компилятора, что бы он узнал. И не может требовать, на данный момент.
но гарантий нет

В контексте:
C++ компиляторы такое осилят?

Стандарт мало кого волнует. Они могут и смогут. И никаких гарантий со стороны стандарта компиляторам для этого не нужно.

Нужно, если компилятор будет выдавать ошибку компиляции. Пользователям не понравится, если компиляторХ компилирует с флагами по умолчанию, а компиляторУ — вываливается с ошибкой. Компиляторы могут выдавать предупреждения. Но на сегодняшний день это не может работать в общем случае.
Пользователям не понравится, если компиляторХ компилирует с флагами по умолчанию, а компиляторУ — вываливается с ошибкой.
Как вариант, можно проверять лишь при нестандартном флаге. Как с -Werror сделано.
Скорее всего так и будет. Но опять же, мне кажется, сделать такой C++ компилятор, что бы он всегда мог правильно определить область значений параметров в заданном контексте нереально. А значит часть контрактов не смогут быть проверены на этапе компиляции.
Все эти рассуждения про «компиляторы» имеют очень мало смысла в контексте современного С++, у которого существует только 2 живых компилятора и один полу-живой(вендорлочный). Все они это умеют, а остальные «компиляторы» не умеют даже с++17, не говоря уже о с++20.

Поэтому для подавляющего большинства пользователей С++ это будет работать, даже если не будет обязательным, либо вообще указано стандартом. А общий случай это подавляющие большинство пользователей мало интересует. Пусть работает где-то, чем не работает везде. И это правильно.

Даже с чисто формальной ТЗ стандарта подобное поведение можно включить в «необязательно» и пусть те, кто не могут — не могут дальше.

Пользователям не понравится, если компиляторХ компилирует с флагами по умолчанию, а компиляторУ — вываливается с ошибкой.

Основная фича современных компиляторов работает именно по такой схеме. У одного компилятора может быть ворнинг у другого нет, это мало кого заботит и никаких проблем не вызывает.

Не говоря уже о самой поддержке стандартов, где код вообще может не собираться. И не собирается.

С технической точки зрения компилятор всё знает и никаких проблем нет. Если даже не хочется вводить это в стандарт — компилятор сможет за этим следить. И даже если не хочется обязывать все компиляторы делать такие «сложные» штуки, то, как я уже говорил, не обязательно включать это в обязательную часть.

Мой тезис: никакие гарантии от компилятора по отношению к контрактам в contracts proposal не вводятся. И не факт что какие-то серьезные гарантии могут быть введены со временем. Contract-based programming с гарантий на уровне компилятора — это не решенная на данный момент задача. И нет предпосылок к тому, что в C++ будет достигнуто решение.
остальные «компиляторы» не умеют даже с++17
software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler
Остальные не проверял. Уже как минимум 4: g++, clang, microsoft, intel — немало.
для подавляющего большинства пользователей С++ это будет работать
Будет как-то работать непредсказуемым образом. Типа как статический анализ.
одного компилятора может быть ворнинг у другого нет
Но не еррор. Разговор начался с «не скомпилируется с ошибкой», подразумевая гарантированное поведение, на которое можно положиться.
Не говоря уже о самой поддержке стандартов, где код вообще может не собираться. И не собирается.
Если поддержка соотв. стандарта не объявлена. Если объявлена — в основном всё работает или считается багом и чинится.
С технической точки зрения компилятор всё знает и никаких проблем нет.
Только в теории. Если бы всё было так просто, были бы мейнстримные языки с compile-time contract based design, а их до сих пор не существует! Даже в Rust не могут договорится о том, как их сделать и делать ли.
компилятор сможет за этим следить.
В общем случае — не сможет. Как и не сможет надёжно оптимизировать код так же качественно, как тренированный человек. Максимум что можно будет сделать — это ещё один тип диагностик в статическом анализе, которые могут словить, а могут и не словить проблему.
Contract-based programming с гарантий на уровне компилятора — это не решенная на данный момент задача.

На каком основании?

Откуда вообще вы взяли свой тезис, если отвечал на:

C++ компиляторы такое осилят?

Как-то вы быстро тему поменяли. Ничего похоже на ваши тезисы я в этой ветке не видел. Зачем вы начали ссылаться на «осилят», если сейчас это для вас перестало быть существенным, и вообще играть какую-либо роль?

software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler

И? Вы увидели там c17 и вам показалось, что оно умеет в с++17? Нет, вам только показалось.

Остальные не проверял.

Остальных нет.
g++, clang

Да.
microsoft

Кое как.

intel — немало.

Нет.

И того 2.5, о которых я и говорил. Больше нет.

Будет как-то работать непредсказуемым образом. Типа как статический анализ.

И? Из этого что-то следует? Нет. Опять же, я тут вижу попытку манипулировать, ведь оно работает очень предсказуемым образом. Оно не гарантирует срабатывание на все ошибки, но на те, что срабатывает — оно срабатывает предсказуемо.

Но не еррор. Разговор начался с «не скомпилируется с ошибкой», подразумевая гарантированное поведение, на которое можно положиться.

На ворнинг можно положиться. Так же, к чему тут эта отсылка на ерррор — мне не ясно. С++ такой язык, а рантайм такая штука, что ничего предсказать нельзя и отсутствие ошибок не говорит о каком-то «положиться». Вообще нигде и никогда это ни о чём не говорит. Если вы пытаетесь апеллировать к этому, то это не тот язык, как и не любой другой в этой реальности.

Если поддержка соотв. стандарта не объявлена. Если объявлена — в основном всё работает или считается багом и чинится.

Это так смешно читать после того, как вы засыпались с поддержкой С++17 у icc.

Ваши рассуждения не соответствуют реальности, в приведенных вами компиляторах(а других нет) добавление ключика не означает 100% поддержки, а означает лишь как минимум базову поддержу. Нюансов там может быть много.

Только в теории.

В реальности, особенно в вашем примере.

Если бы всё было так просто, были бы мейнстримные языки с compile-time contract based design, а их до сих пор не существует!

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

А вы попробуйте собрать хоть что-то так, чтобы компилятор в рамках одной единицы трансляции имел доступ к коду всей вашей программы(ведь рантайм в это понятие так же входит). В общем случае, да в и 99% реальных случаев — это невозможно. Даже лто вам не поможет в ситуации в динамически слинкованным рантаймом. Без этого даже в теории определить наличие чистоты у всех функций не представляется возможным.

Даже в Rust не могут договорится о том, как их сделать и делать ли.

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

В общем случае — не сможет.

Я уже писал об этом — это мало кого интересует. Никакая собранная программа на С++ в общем случае работать корректно не может. Дальше что?

Максимум что можно будет сделать — это ещё один тип диагностик в статическом анализе, которые могут словить, а могут и не словить проблему.

И? К чему это всё. Как минимум в ситуации, когда оно может словить проблему статически — оно не будет генерировать рантайм-проверки. Это уже профит, 100% профит.

По поводу самой отсылки к каким-то гарантиям. Они никого не интересуют. Если людям это даст хоть какие-то проверки — этого будет достаточно. И всем будет абсолютно пофиг на то, что что-то там не можется. Подобные рассуждения хороши для посраться на форуме, но не более.

Как-то вы быстро тему поменяли
Да нет, просто «осилят» было в контексте, который Вы проигнорировали.
вам показалось
Нет, я увидел список поддерживаемых из c++17 фич, которых на данный момент 75% и динамика на увеличение с каждой версией.
Остальных нет.

EDG eccp более 80%, Intel > 75%, PGI ~50%, а что будет через 2 года?
На ворнинг можно положиться.
Только если он гарантируется. Здесь же не факт, скорее будет как в статических анализаторах.
вы засыпались с поддержкой С++17 у icc
Засыпался? тем что привёл ссылку на список поддерживаемых и не поддерживаемых фич? Я не говорил, что icc поддерживает c++17, лишь указал что он движется к этому.
Дело не в этом
Не в чём?
ведь если состояние зависит от рандомного поведения рантайма, то уже никакие теории не помогут.
По идее в таком случае области определения — R или что там, в зависимости от типа. Вот и вся теория.
определить наличие чистоты у всех функций не представляется возможным.
Я об этом говорил, что это в C++ это нереально.
Раст не показатель
Согласен, вы знаете примеры, где реализован compile time design by contract?
Дальше что?
а то, что исходное утверждение
вам о возможном нарушении контракта скажет компилятор еще на этапе сборки.
не совсем корректно т.к. пропущено «если повезёт».
По поводу самой отсылки к каким-то гарантиям. Они никого не интересуют.
Ну как, исследования то идут.
Когда я писал «уже как минимум 4», я имел ввиду, конечно, что поддерживают c++17 хоть как-то, а не «вполне», сори.
Там вся куда сложнее, но мы потихоньку до этого дойдём.
Давайте по по порядку, чтобы сложнее было уходить от ответов:

Если поддержка соотв. стандарта не объявлена. Если объявлена — в основном всё работает или считается багом и чинится.

EDG eccp более 80%, Intel > 75%, PGI ~50%

Дак работает, либо на 50%?

У вас вилка, если вы признаете, что «в основном работает» — это 50%+, то ваши рассуждения на тему «должно собираться» — не работают, ведь оно попросту не будет собираться.

Это является попыткой опровержения моего тезиса:

Не говоря уже о самой поддержке стандартов, где код вообще может не собираться. И не собирается.


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

Ваши два ответа мне противоречат, по крайней мере, друг другу. Разрешите противоречие.

Дак работает, либо на 50%?
Если объявлена, то работает. Что объявлено, то и работает.
Заявленная поддержка стандарта должна позволять компилятору собирать то, что заявлено. На данный момент 2.5 компилятора заявили практически полную поддержку, и еще 2-3 двигаются в этом направлении, два из которых довольно близки к достижению полноценной поддержки, как мне кажется.
Если объявлена, то работает.

Она не работает, значит не объявлена(на самом деле объявлена(Use compiler option -std=c++17), но это будет слишком просто), значит не поддерживает, значит не собирается.

Таким образом ваша попытка оспорить:

Не говоря уже о самой поддержке стандартов, где код вообще может не собираться. И не собирается.

Целиком и полностью несостоятельна.

Точно так же, как и:

остальные «компиляторы» не умеют даже с++17

software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler
Остальные не проверял. Уже как минимум 4: g++, clang, microsoft, intel — немало.

Таким образом, вы пытались выдавать тех, кто не умеет:

два из которых довольно близки к достижению полноценной поддержки

Близки не значат могут. За тех, кто умеет. Это нехорошо.

Таким образом, как я и говорил, умеют в с++17 только 2.5 компилятора.
Целиком и полностью несостоятельна
Ну почему же. Поддержка может быть частичной.
остальные «компиляторы» не умеют даже с++17
Умеют частично, как минимум 2 на более чем 70% фич. Умеют почти полностью 2, и один — с натяжкой. В той или иной мере — не менее 5.
Ну почему же. Поддержка может быть частичной.

Абсолютно неважно, она несостоятельна в любом случае, если этот случай не «полная поддержка». Напомню, что вы оспаривали возможно собираться/не собираться на разных компиляторах стандартного кода. С частичной поддержкой — он так и будет, то собираться, то не собираться и никакой «уверенности» у вас не будет.

Умеют частично, как минимум 2 на более чем 70% фич.

Инфу вы скорее всего взяли отсюда:

en.cppreference.com/w/cpp/compiler_support

Смотрим на поддержу с++14 у icc — даже она не полная. Я проверил constexpr у complex — его нет, т.е. NA == не работает.

Смотрим на поддержу С++17 — она никакая. Нету там 70%. От силы 50%

Что такое «EDG eccp» мне неведомо. Гугл находит только какой-то фронтед, т.е. это вообще не компилятор, либо гугл о нём не знает.

И того, 2.5 компилятора(можно даже msvc записать третьим, если поверить в честность МС. Но он вендорлочный, а так же слаб как компилятор) + какие-то куски поддержки у icc. Всё, больше мир компиляторов не знает.

icc я считал по таблице с сайта интел, там 9 из 37 пунктов указаны без поддержки — ~75% поддерживается. Но я не знаю, есть ли другие. Точнее я знаю, что есть какие-то специфические компиляторы для HPC от вендоров (IBM, HP?), но не могу сказать ничего конкретного.
icc я считал по таблице с сайта интел, там 9 из 37 пунктов указаны без поддержки — ~75% поддерживается.

Ну они как минимум могут написать не все пункты из стандарта(что мы и видим) + разные пункты не равнозначны.

en.cppreference.com/w/cpp/compiler_support — вот тут есть и оракловский и айбиэмовский и хпешный. Результаты нулевые.

Хоть icc и стал как-то догонять стандарт, а не то, что было раньше. Но всё же — чуда не произошло. Компилятор этот достаточно специфический и мало претендует на звание передового.

Вот и остаются gcc/clang из портабельных + один вендорлочный, который недавно так же начал догонять. Посмотрим, на сколько его хватит.

Ветку обсуждения поддержи стандартов со стороны компиляторов постигла неудача( с вашей стороны), поэтому продолжим.

Не в чём?

Это очевидно и был дан конкретный пример, компилятор ограничивает уже давно не сам компилятор, а подходы к использованию этого компилятора, т.е. к компиляции кода.

Я об этом говорил, что это в C++ это нереально.

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

Согласен, вы знаете примеры, где реализован compile time design by contract?

Зачем вы пытаетесь пропихнуть новые, свободно-трактуемые, термины в обсуждение? Это настолько глупо.

Любая реализация чего-либо сравнивается с идеалом, причём этот идеал определяется не вашими фантазиями на тему. У нас есть какой-то код, есть некий порог, объективный порог — то, даже чего не может пойти статический анализ. За него зайти нельзя.

И нет смысла рассуждать о том, что находится за этим порогом. Это просто демагогия и попытка отмыть свои суждения. Если конкретней, то нет смысла рассуждать о том, чем в принципе существовать не может. Не может существовать 100% полного как compile time design by contract, так и рантайм. Всегда будут какие-то допущения, да в части кода исполняющего в рантайме ратайм проверки более мощные, но они имеют и свои минусы, которые на поверхности.

В какой-то мере design by contract существует в компиляторах и сейчас, только он не прямой и эти контракты описываются косвенно. Ссылаться же на другие языки не имеет смысла, С/С++ имеет самые передовой компилятор в сравнение с которыми все остальные — детский садик.

не совсем корректно т.к. пропущено «если повезёт».

Во-первых я говорил не об этом, а вторых оно корректно. Ваши «если повезёт» — глупости. Всё в этом мире работает в ситуации «если повезёт». Но дело не в этом.

Давайте подумаем:
о возможном нарушении контракта

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

Таким образом ситуации в которой контракт будет нарушен, но компилятор об этом не скажет — быть не может, может быть ситуация «нарушений нет, а показывает, что „возможно есть“», но это не проблема.

Ну как, исследования то идут.

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

Есть два варианта: это изучать и основывать свой анализ на поведение конкретного окружения, но это не будет «в общем случае». Либо, создавать искусственное окружение с какими-то заранее определёнными свойствами, либо другой путь того же — отсекать возможность у программы делать то, результат чего может быть непредсказуем.

Но всё это сужение общего случая.

Ветку обсуждения поддержи стандартов со стороны компиляторов постигла неудача( с вашей стороны),
Вы завели диспут по поводу второстепенного по отношению к обсуждаемой теме технического нюанса, с которым я и не спорил, и сами у себя его выиграли. Ну ОК.

С чем вы спорите? С каким утвержденим? Напомню, мой основной тезис:
В C++ нельзя положиться на то, что нарушения контрактов (как они есть в текущем proposal) будут обнаружены на этапе компиляции, как писал изначально Antervis. Есть некоторое число несложных частных случаев, когда это сработает, но в основном — нет. Это и понятно, ведь, если я правильно понял, contracts proposal — это немногим более чем новый синтаксис для assert. Если Вы с этим тезисом согласны, то о чем спорите?

В общем случае поведение рантайма в компилтайме предсказать невозможно, точка.
Для меня не очевидно, почему в рамках конкретного (возможно, пока не созданного) языка программирования это невозможно, возможно с исключениями типа unsafe в Rust, но всё же. Есть же seL4 и Spec#.
В однопоточном случае обнаружить нарушение контракта компилятор скорее всего сможет. Или, как минимум, потенциальное нарушение контракта при отсутствии ub (типа записи через const_cast по const &).

Что до многопоточного случая — формально, data race без примитивов синхронизации — ub. А при наличии примитивов синхронизации уже известно, где теряются гарантии контракта.

По сути, в коде без ub контракты будут работать на уровне поддержки их компилятором.
В однопоточном случае обнаружить нарушение контракта компилятор скорее всего сможет
Не верится в «скорее всего». Для этого фактически компилятор должен свести условие контракта до constexpr!, что в C++ чаще невозможно, чем возможно.
По сути, в коде без ub контракты будут работать на уровне поддержки их компилятором.
Что Вы имеете ввиду? Согласно пропозала полная поддержка компилятора означает просто поддержку проверки в runtime (как assert), если я правильно понял.
Кроме того, как компилятор будет отличать многопоточный случай от однопоточного?
Для этого фактически компилятор должен свести условие контракта до constexpr!, что в C++ чаще невозможно, чем возможно.

Компилятор может оптимизировать и то, что не constexpr, так ведь? Только гарантий нет. Вот здесь то же самое.
Что Вы имеете ввиду? Согласно пропозала полная поддержка компилятора означает просто поддержку проверки в runtime (как assert), если я правильно понял.

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

отслеживать входы/выходы из критических секций.
Компилятор может оптимизировать и то, что не constexpr, так ведь?
Так. То есть вероятность, что нетривиальный контракт будет проверен на этапе компиляции примерно такая же, как и вероятность того, что аналогичное выражение было бы оптимизировано компилятором до `noop`. Невысокая, как мне кажется. Ну и, что хуже всего — это то, что программисту будет очень трудно уверенно предсказать, когда это сработает, а когда нет. Для оптимизаций это нестрашно, а для контрактов — весьма неприятно.
Так там же принцип «better safe than sorry» — если компилятор не может вывести гарантии для requires, он попросту предупредит «вот здесь может быть нарушен контракт». А там уже дальше либо программист еще гарантию припишет, либо будет работать с лишней проверкой. В самом худшем случае мы получим то же самое число лишних проверок пред/постусловий, что и в коде до контрактов. В конце концов, сейчас многие проверки (типа пресловутых nullptr?) оптимизируются из-за дублирований, а с контрактами у компилятора больше инфы
он попросту предупредит «вот здесь может быть нарушен контракт».
Если он будет предупреждать об этом в 9 контрактах из 10, то толку? С лишней проверкой будет работать только в дебаг билде.
В самом худшем случае мы получим то же самое число лишних проверок пред/постусловий, что и в коде до контрактов
Ну да, точно как с assert.
почему для вас «отсутствие формальных гарантий» эквивалентно «будет работать в 1/10 случаев»?
Так я примерно оцениваю возможности компилятора оптимизировать нетривиальный код типа argument.is_valid() до noop
Вы завели диспут по поводу второстепенного по отношению к обсуждаемой теме технического нюанса, с которым я и не спорил, и сами у себя его выиграли. Ну ОК.

Таких нюансов было много, просто они очень показательны. Они говорят о серьёзности аргументальной базы.

В C++ нельзя положиться на то, что нарушения контрактов (как они есть в текущем proposal) будут обнаружены на этапе компиляции,

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

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

Вы тут начали вилять «а как так компилятор может собирать/не собирать код по своей воле» — вам ответили «так же, как он это делает сейчас», на что вы начали вилять в сторону «не делает, если он поддерживает(заявляет об этом) стандарт — он не может не собрать код). На что я вам ответил и доказал, что может и делает.

Это и понятно, ведь, если я правильно понял, contracts proposal — это немногим более чем новый синтаксис для assert.

Нет, вы ещё утверждали то, что „они ничего не отличаются от асертов“/»преимуществ не имеют", а как мы выяснили — имеют.

Но вы продолжаете игнорировать свои начальные тезисы и ссылать на то, что придумали после.

Для меня не очевидно, почему в рамках конкретного (возможно, пока не созданного) языка программирования это невозможно, возможно с исключениями типа unsafe в Rust,


«За исключениями» — противоречит общему случаю. У общего случая нет исключений, на то он и общий. Вам это тоже не очевидно?

Есть же seL4 и Spec#.

Это всё типичная подмена понятий и манипуляции. Никакого отношения они к гарантиям не имеют и никакое поведение рантайма не предсказывают.

Они просто живут в песочницах, которые им организовывают те самые песочницы на языка, которые ничего не гарантируют и не предсказываю, а предсказывают конкретные люди и для конкретных случаях. За рамках этих случаев — песочницы не работают.

Это не контекст нашего разговора
А что же это? Это то сообщение, на которое я отвечал. Как это может не быть контекстом? Вы продолжаете этот контекст игнорировать.
Вы так и не показали определяющих контекст ваших заглавных постов
Многократно показывал. Повторяю последний раз.
Вот комментарий, на который я отвечал:
вам о возможном нарушении контракта скажет компилятор еще на этапе сборки.
И мы с автором уже разобрались в вопросе. Что Вы цепляетесь к каким-то вырванным из контекста репликам?
это ваши попытки отмыть себя
Что Вас так заботят мои внутренние мотивации? Кругом враги? Оставляю вопрос об истоках хамства, глупостей и демагогии в Ваших постах Вам на самостоятельную проработку.
Многократно показывал. Повторяю последний раз.
Вот комментарий, на который я отвечал:

Меня мало интересует то, на что вы где-то отвечали. Мне нужны конкретные ваши утверждения, и они у меня есть и я их вам показывал. И в каждом из них вас постигла неудача.

Контекст определяют ваши ответы, которые были до моих. ВАШИ, а не чьи-то. Ссылать на левый пост задним числом трактовать его хочется — это не контекст.

И мы с автором уже разобрались в вопросе. Что Вы цепляетесь к каким-то вырванным из контекста репликам?

Я не цепляюсь, я цепляюсь к конкретным вашим неудачам. Я отвечаю за свои тезисы и отвечаю на ваши. Ссылки на левые комменты, которые вы пытаетесь задним числом трактовать как удобно — не работаюют.

Что Вас так заботят мои внутренние мотивации?

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

Неудачи есть — пациент врёт. А раз он врёт, то ни о какой объективности и вменяемости в споре с ним речи быть не может.

Оставляю вопрос об истоках хамства

Покажите хамство? Я думаю точно так же, как вы мне показали четвёртый поддерживающий С++17 компилятор.

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

И где же они? Где глупости, почему вы не отвечаете и не показываете их? Тоже самое вы говорили и о компиляторах, но оказалось, что вы просто болтали. И у меня есть прецедент на который я могу постоянно ссылаться, а значит — все ваши попытки придумывать новые оправдания — тщетны.

Меня мало интересует то, на что вы где-то отвечали.
Я и говорю, Вы сами с собой спорите и вырываете мои слова из контекста, который задаётся всеми предыдущими репликами в диалоге, не только моими. Как крайний пример «согласен» вообще без предшествующей реплики не имеет смысла.
Ссылки на левые комменты, которые вы пытаетесь задним числом трактовать
Задним числом? Я не менял позицию по поводу той реплики и даже уже коротко излагал её повторно. Все мои реплики станут Вам понятны, если вы прочитаете диалог не с середины, а с начала.
Да, юлить можно сколько угодно
Аппелировать к личности тоже, но мне это не интересно. По сути Вам сказать, видимо нечего.
я ловлю
Никого Вы не ловите, только демагогию разводите, вырывая из контекста и не понимая, что прочитали.
пациент врёт
Кругом враги и дураки?
вы мне показали четвёртый поддерживающий С++17 компилятор.
Ну снова вы за меня додумываете и демагогию разводите. Так-то и одного поддерживающего С++17 компилятора не существует, у всех есть хотя бы небольшое несоответствие. Там в контексте было понятно, что речь шла о, возможно, частичной поддержке.
почему вы не отвечаете и не показываете их
Потому что это мне не интересно, меня Ваша личность не интересует, мне не нужно самоутверждаться, пытаясь кого-то поймать на чем-то.
у меня есть прецедент на который я могу постоянно ссылаться
Во первых, Вы можете ссылаться только на свою демагогию и придирки не по теме. Во-вторых даже если бы я ошибся, это ничего не доказывает.
Это бесполезно, я вижу одно враньё. Но мы пойдём другим путём, я докажу, что данный человек — болтун. Очень просто юлить и врать на абстрактные темы, а вот некие конкретные темы, тот же разговор о С++17 достаточно очевиден и тут сложно врать.

Ну снова вы за меня додумываете и демагогию разводите.


остальные «компиляторы» не умеют даже с++17

software.intel.com/en-us/articles/c17-features-supported-by-intel-c-compiler
Остальные не проверял. Уже как минимум 4: g++, clang, microsoft, intel — немало.


Т.е. тут человек отрицал моё утверждение, в противном случае он бы это не писал. Это явное отрицание:

С чего же всё началось:

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


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

Это человек пытался крыть тем, что вы видите выше. Т.е. отсылкой на то, что это плохо.

На что я ответил тем, что вы так же видите выше. Компиляторы итак не собирают один и тот же код ДАЖЕ С ЛЕВЫМИ ФЛАГАМИ, не говоря уже о «по умолчанию».

И того мы видим тут явную ошибку. Ошибка и по части утверждений в сторону поддержки стандарта у более, чем 2.5 компиляторов. И в части попытки съехать на «компиляторы не могут компилировать/не компилировать код по своему желанию», которая так же оказалась неудачной. Могут, при это ещё как.

Я уже один раз позволил человеку уйти от ответа, но похоже он ничего не понял и продолжает врать. На этот раз такого не будет.

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

НЛО прилетело и опубликовало эту надпись здесь
Всё очень просто. Вы отвечаете на «предсказать поведение в рантайме», отвечаете примерами неких языков. Эти языки существуют в рамках не реальных, а виртуальных исполнителей. Т.е. виртуальных машин с виртуальной же моделью памяти и всем остальным.

Эти машины реализуются на языка, для которых «предсказать поведение в рантайме» невозможно. Авторы этих машин идут другим путём, они берут некий конкретный исполнитель, не кую архитектуру, поведение которой достаточно предсказуемо. Это и позволяет им получить предсказуемое поведение.

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

Таким образом получается реализовать то, что работает не в одних, а в нескольких условиях. В любом случае — это не является общим случаем.

Далее, те языки, которые работают в рамках этой машины — очень ограничены. Их возможности заканчиваются за рамками этой машины, они не позволяют хоть как-то коммуницировать с реальным миром. Для этого им нужны прокладки. Они не являются так же «языками общего случая».

Таким образом, упомянутый вами языки не являются предсказуемыми. Они существует в рамках непредсказуемой ВМ, непредсказуемых биндингов, ограниченных возможностей. Каждый из этих пунктов целиком и полностью противоречит понятию «общий случай».
НЛО прилетело и опубликовало эту надпись здесь
Даже если говорить о языках, о всякой хардкорщине вроде языков с зависимыми типами, некоторые из них вполне себе могут взаимодействовать с внешним миром.

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

Естественно, есть некоторые предположения о нижележащей реализации.

Дело не в этом, каждая реализация обладает своими свойства и завязка на конкретные реализации работает только в рамках этих конкретных реализаций. Всё, точка. Учитывать нюансы работы каждой конкретной платформы в общем случае невозможно.

Ни о каких микродах и космических лучах речи не шло — это было бы слишком просто, для меня.
Всё в этом мире работает в ситуации «если повезёт».
Это демагогия. В контексте нашего разговора примером гарантированного поведение (в противоположность «если повезёт») являются гарантии, которые обеспечивает Rust или Haskell, например. В C++, contacts proposal не предполагает вообще никаких дополнительных гарантий, кроме тех, что есть у assert. Я предполагаю, что эта ситуация, к сожалению, фундаментально не улучшится из-за особенностей C++: его системы типов, и устройства C++ компиляторов которое продиктовано самим языком.
искусственное окружение с какими-то заранее определёнными свойствами
Стандарт языка программирования и есть этим искусственным окружением. C++ не достаточно сужает контекст что бы реализовать сколь-нибудь серьезный static contact-based programming, как мне кажется.
В контексте нашего разговора примером гарантированного поведение (в противоположность «если повезёт»)

Это не контекст нашего разговора — это ваши попытки отмыть себя. Вы так и не показали определяющих контекст ваших заглавных постов(не тех, которые были после, а те, которые были в этой ветке на момент моего ответа).

которые обеспечивает Rust или Haskell

Ничего они не обеспечивают «в общем случае» и я уже об этом говорил. Но будучи вами очень удобно спорить — можно просто брать и игнорировать неудобные тезисы/ответы.

Всё это работает в рамках неприемлемых для С++ рамках, в которых существует раст/хаскель. Что тут делает хаскель — мне неясно. Но у раста даже формально есть ответ — unsafe и всё, всё очень быстро и сразу перестаёт работать.

В C++, contacts proposal не предполагает вообще никаких дополнительных гарантий, кроме тех, что есть у assert.

«Не предлагает» не значит, что их не может быть. proposal не запрещает компилятору в каких-то случаях их выпиливать на базе своих, внутренних, обоснований.

Вам на это указали, вы теперь пытаетесь ехать в сторону «а гарантий то нет» — только об этом я не говорил, да и вы тоже.

Стандарт языка программирования и есть этим искусственным окружением.

Не в случае С++.

C++ не достаточно сужает контекст что бы реализовать сколь-нибудь серьезный static contact-based programming, как мне кажется.

Оно и не нужно. Нужно лишь лучше ассертов, а всё остальное — ваши придумки.

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


Я не об этом говорил. Я говорил о том, что если какую-то часть рантайм-проверок можно свести к компилтайму, то нужно это делать и это профитно.

А все рассуждения уровня «ну не все же можно» — простая демагогия, когда нету ответов.

По части оптимизации — да. По части системы типов — ну…


Это простая ссылка на то, чего в С++ нет, но это не значит, что это является чем-то более сложным, чем то, что есть сейчас в С++.

Система типов не такая, но заморочек так не мало, и её реализации требует не меньшего кол-ва логики, нежели любой другая, которая «ну...».

НЛО прилетело и опубликовало эту надпись здесь
Вы ещё говорили о том, что рантайм-проверки более мощные.

Естественно, что в рамках рантайма рантайм-проверки более мощные.

Либо у нас с вами сильно разное определение мощности, либо это совсем не так.

В чём конкретно проблема?
НЛО прилетело и опубликовало эту надпись здесь
Дело не только в информации, ею всё не ограничиваются. Состояние исполнителя, факт его работы, состояние памяти и т.п.

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

В контексте кодогенерации. Прокомментирую это более подробно. В случае с данными «по сети»/«из файла» я уйду от проверок статически. Не ото всех, но уйду. Статически я могу имплементировать оптимальные проверки. Таким образом, даже если некая валидация данных происходит в рантайме — чистые компилтайм-проверки проигрывают миксу.
НЛО прилетело и опубликовало эту надпись здесь
А в каком языке это хорошо работает? На сколько я знаю, в передовых (?) в плане design by contract языках Eiffel и Spec# так и не довели идею до того что бы можно было интегрировать в мейнстримные языки.
НЛО прилетело и опубликовало эту надпись здесь
Спасибо за ликбез. Исправляю свой тезис: «не решенная в мейнстримных языках задача».
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Можно, только не нужно дёргать фразы. Там говорилось «положится» в контексте false-positive. Компилятор всегда может сказать — есть гарантия, либо её нет. И если он дал эту гарантию — она есть и на неё можно положиться.

НЛО прилетело и опубликовало эту надпись здесь
Решённая. Просто не в С++.
А где? Самое продвинутое, что мне известно — это Eiffel и Spec# и не то что бы там прям вот всё гладко. Как я понял, авторы решили, что для внедрения в мейнстрим не готово. Тянуть доказательства вручную через весь код — это, как мне кажется не достаточно хорошее решение. Слишком много геморроя, нужна автоматизация.
НЛО прилетело и опубликовало эту надпись здесь
ну почему же. Вот есть у вас, скажем, простое выражение foo(bar());. bar() обещает (ensures) вернуть вам ненулевой unique_ptr, который foo() ожидает (expects) на входе. Перепроверять гарантии не нужно, потому что компилятор убедится в выполнении контракта в bar() и выкинет лишние проверки внутри foo()
компилятор убедится в выполнении контракта в bar() и выкинет лишние проверки внутри foo()
А как? А что если у нас многопоточный код?
НЛО прилетело и опубликовало эту надпись здесь
Нельзя просто так взять и посмотреть в ассерты библиотечных функций.
НЛО прилетело и опубликовало эту надпись здесь
модули тоже могут распространяться в виде бинарников
НЛО прилетело и опубликовало эту надпись здесь
что мешает распространять бинарник с описанием модуля и библиотеку с реализацией двумя файлами?
Режим без runtime проверок аналогичен режиму с выкинутыми assert — не гарантирует безопасности. Т.е. если программа корректно скомпилировалась в режиме «все проверки» ещё не значит, что без проверок все будет ОК, т.к. результат проверки зависит от рантайм-значений.
механизм для уменьшения числа проверок в рантайме
И чем же контракты в этом плане выигрывают у std::assert? Что такого в них есть, что позволит снизить число проверок в рантайме, по сравнению с использованием assert?
как минимум, гарантии функции (ensures). А еще проверки предусловий вынесены из функции, соответственно вы будете знать о том, что библиотечная функция не умеет принимать nullptr на этапе компиляции, а не отладки.
чем ensures отличается от assert перед return? С точки зрения компилятора?
вы будете знать о том, что библиотечная функция не умеет принимать nullptr на этапе компиляции
Нет, придётся смотреть документацию всё равно. Узнать о том, что библиотечная функция не умеет nullptr можно будет только намеренно подав в неё nullptr и запустив эту ветку кода, дождаться исключения.
чем ensures отличается от assert перед return? С точки зрения компилятора?

а если компилятор не знает о том assert'е?

Нет, придётся смотреть документацию всё равно. Узнать о том, что библиотечная функция не умеет nullptr можно будет только намеренно подав в неё nullptr и запустив эту ветку кода, дождаться исключения.

Если у функции объявлен контракт, компилятор даже не соберет код с ошибкой «вы собираетесь передать nullptr в функцию, которая его не ждет» или «здесь возможен nullptr, а вот эта функция его не умеет, добавьте проверку»
а если компилятор не знает о том assert'е?
Согласен, в случае бинарной библиотеки контракт — это удобный способ сохранить assert <в header файле>.
не соберет код с ошибкой «вы собираетесь передать nullptr в функцию, которая его не ждет»

int value(int* ptr) 
[[expects: ptr != nullptr; ]]
{return *ptr;}
int main()
{
  int a=1;
  int* p=&a;
  //in parallel thread: p=nullptr;
  return value(p);
}

Компилятор не знает на этапе компиляции, что такое p.
«здесь возможен nullptr, а вот эта функция его не умеет, добавьте проверку»
Врядли компилятор такое сможет в общем случае. Вывести всё множество возможных значений параметра в c++ звучит фантастически. Нет даже механизма указать, что p — !nullptr, можно только надеяться, что компилятор откуда-то сам это выведет. Но нет никаких гарантий, что там, где один компилятор выведет — другой тоже осилит, этого нет в стандарте.
в однопоточном случае компилятор очень даже может вывести nullptr/!nullptr, иначе бы он попросту не умел оптимизировать код. Контракты только увеличат информацию, которой располагает компилятор.

Что до многопоточного — наверно, как всегда надо аккуратно проектировать и использовать потокобезопасные инструменты. А ошибки ловить контрактами в отладочном режиме. Даже в вашем примере, в силу отсутствия volatile, после оптимизаций в value(p) может передаться &a.
Может, но не гарантировано. Мы обсуждаем то, будет ли компилятор выдавать ошибку компиляции в случае нарушения контракта. Я говорю что не будет т.к. нет возможности обеспечить одинаковое поведение для разных компиляторов. Ошибка компиляции должна гарантироваться (стандартом) на всех компиляторах, этого обеспечить на данный момент нельзя. На этапе исполнения — да, все компиляторы смогут проверять такое.
Ошибка компиляции должна гарантироваться (стандартом) на всех компиляторах

Не обязательно. Стандарт описывает базовый механизм описания контрактов, а конечному компилятору ничего не мешает выдавать ошибки/предупреждения без оглядки на стандарт, что он и делает во многих других случаях.

Поэтому, в контексте «а могут ли больше, чем ассерты?» — могут. И стандарту для этого гарантировать ничего не нужно. А в ситуации с асертами — этим никто заморачиваться не будет, и там даже «могут» не сработает.

Стандарт описывает базовый механизм описания контрактов
Но не требования к проверке их выполнения, кроме тех что определены для assert. Поэтому я и говорю, что на данный момент контракты — это скорее способ документирования.
Какие есть случаи, когда со стандартными флагами компиляторы выдают разные ошибки компиляции и это воспринимается как должное?
Но не требования к проверке их выполнения, кроме тех что определены для assert.

Нету, но разговор был не об этом. Вы просили назвать преимущества — вам их назвали. Ссылки на «а вот в стандарте нет» тут мало применимы, ворнингов и прочего статического анализа в стандарте тоже нет, но это же не значит, что его нет.

Так и тут. Есть механизм, который позволяет реализовать этот анализ намного проще и понятней. И естественно, что он лучше, нежели рандомные ассерты. И шансы на то, что компиляторы реализуют какие-то проверки для них — несоизмеримо выше, нежели в ситуации с асертами.

Преимущество очевидно.

Какие есть случаи, когда со стандартными флагами компиляторы выдают разные ошибки компиляции и это воспринимается как должное?

Ну дак это ничему не мешает, в стандартном режиме можно и подавлять ошибки. В любом случае ворнинги никому не помешают, а уже этого достаточно. А Werror — есть всегда.
Вы просили назвать преимущества — вам их назвали
Не совсем, я отвечал на «не соберет код с ошибкой» и говорил, что в общем случае компилятор не сможет выдать ошибку. А в остальном я согласен — такой себе assert-based static analysis.
И чем же контракты в этом плане выигрывают у std::assert? Что такого в них есть, что позволит снизить число проверок в рантайме, по сравнению с использованием assert?

Вот заглавие ветки. Очевидно, что я на это ответил. Упрощение реализации статических проверок уже является преимуществом над ассертами, и так же позволяет сократить вычисления в рантайме.

Нет смысла гонятся за мистическим «общим случаем», которого нигде в реальности нет. У нас есть простой выбор — иметь хоть что-то, либо не иметь ничего. А сидеть без ничего обвиняя тех, кто предложил хоть что-то в том, что их предложение «работает не всегда» — пустая затея.

Вот заглавие ветки.
Но это ещё не весь контекст.
Нет смысла гонятся за мистическим «общим случаем», которого нигде в реальности нет.
А с этим никто и не спорил. Человек написал «вы будете знать о том, что библиотечная функция не умеет принимать nullptr на этапе компиляции» и «не соберет код с ошибкой», а я добавил "… если повезёт". Всё.
Но это ещё не весь контекст.

Нет, весь. Я не видел и не вижу ничего, что добавляло деталей в этот контекст. Может я плохо искал?

Человек написал «вы будете знать о том, что библиотечная функция не умеет принимать nullptr на этапе компиляции» и «не соберет код с ошибкой», а я добавил "… если повезёт". Всё.

Это уже контекст другого человека, а не ваш. К тому же, это целиком и полностью противоречит вашим начальным утверждениям. Не всегда всегда больше никогда, а вы утверждали «никогда»(либо, по крайней мере, «меньше, чем не всегда»).

Это контекст этого обсуждения. Все впосты, предшествующие моему следует учитывать. То что я писал, я писал в ответ на все это обсуждение.
Моё утверждение в том, что «вы будете знать о том, что библиотечная функция не умеет принимать nullptr на этапе компиляции лишь иногда/если повезёт». Где я писал иначе?
Нету никакого контекста, вы его придумали. Я вам задал вопрос — покажите. Говорить о чём-то можно сколько угодно, рассказывая, что что-то есть, когда его нет.

То что я писал, я писал в ответ на все это обсуждение.

Так не бывает, вам показали противоречия в ваших суждениях, когда вы вопрошали о «а что же может быть в сравнении с ассератами» — вам показали, вы начали ехать в сторону «а ну дак это же не гарантирует». Там вы много где засыпались, начиная с того, что само требование гарантий времени компиляции в контексте С++, да и вообще какого-либо реального язык — целиком и полностью несостоятельны.

Вы не просили о гарантиях, никаких гарантий нет и быть не может, но вы продолжаете всё игнорировать и придумать всё новые и новые обстоятельства.

Моё утверждение в том, что

Дайте ссылку на конкретный комментарий с вашим утверждением, который существовал до нашего диалога.
Ассерт выкидывается препроцессором и компилятору не перепадает информация о том, что данная ситуация из ассерта не может произойти при штатном выполнении. Ассерт находится внутри функции и компилятор не может достать информацию о валидном использовании функции, если он видит только forward declaration.
то же самое с контрактами, как я понимаю. Они либо выкидываются на этапе компиляции (тогда нет разницы с assert), либо выполняются в рантайме.
На этапе компиляции код для рантайм проверки контракта может не генерироваться, однако компилятор необходимые ему данные сможет из контракта вытащить и использовать при оптимизации последующего кода.

Ассерты выкидываются на этапе препроцессинга. Поэтому компилятор ничего не знает о том что они там были. Контракты выкидываются самим компилятором. Компилятор выкинет проверку на, например, ненулевой указатель, но все равно сможет использовать "сакральное знание" для оптимизации.

Это справедливо только для бинарных библиотек. Если у компилятора есть исходники — «сакральное знание» из assert ему также доступно. Вот и выходит, что контракты — это doxygen-friendly assert, + требование расположения в header файле подобно шаблонам.
Это было бы практически очень полезно и сделало бы из контрактов функциональный аналог «зависимых типов с эрейзом после тайпчекинга». Я правда, не представляю, как это реализовать в компиляторах.
НЛО прилетело и опубликовало эту надпись здесь
По идее это можно автоматизировать через механизм изменяемых типов/Typestates. Но к плюсам это, конечно, не относится.
НЛО прилетело и опубликовало эту надпись здесь
Ну это когда (под)тип переменной меняется (автоматически) в по ходу выполнения. Например
float sqrt(float x)
{
  if constexpr(stateof(x, float#nonnegative) {
    return ::sqrt(x);
  }
  return NaN;
}
int a=123; //int
int b=(i+5)*2; // int#even
int c=b*b; //int#even#nonnegative
float d=sqrt(c); //call sqrt(float#notNaN#nonnegative)

где «теги» (state) типа (#even, #nonnegative, etc) определяются на этапе компиляции. И в функции они передаются тоже, в идеале прозрачно для пользователя.
НЛО прилетело и опубликовало эту надпись здесь
я в этом совершенно не разбираюсь, просто видел блогпосты с подобными примерами, когда читал про typestate и его выкидывание из Rust.
НЛО прилетело и опубликовало эту надпись здесь
Эти две статьи пересекаются, но не являются подмножествами друг другу :)
Это всё здорово, многое становится действительно проще имплементировать, но с каждым стандартом всё сильнее увеличивается порог входа (потому, что надо ещё уметь читать легаси код). Это хорошо для старых кодеров — их цена повысится, новых будет всё меньше. Но для бизнеса — это довольно печально.
А у Вас есть какие-то предложения, что с этим можно сделать?
Избавляться от обратной совместимости понемногу, т.е. отключить её по дефолту — включать только с определённым флагом при компиляции.
Ну или оставить всё как есть, а продакшн переводить на какой-нибудь другой язык (rust?). Как мне видится — с++ превратился в поле для экспериментов: много удобных фич там появляется, а потом часть медленно кочует в другие, более простые языки.
1. Я думаю, Вы понимаете, что люди просто не будут выключать режим обратной совместимости и всё, так как написаны тонны кода.
2. Для новых проектов не вижу проблемы использовать только свежее подмножество С++
3. Продакшен с С++ на Rust никто так просто не возьмётся переписывать, потому что на это не так просто выбить денег. Да и есть ли смысл?
4. Хм… а мне вот кажется, что наоборот в С++ тянут вещи из других ЯП. В С++ же всё обсасывается годами (что неплохо, имхо)

Выделить подмножество языка, которое будет проще и не будет содержать в себе устаревших и небезопасных фич. Добавить библиотеку, которая поможет использовать именно это подмножество более или менее везде. Добавить статический анализатор, который ругается на любой выход за рамки подмножества, за исключением помеченных сигнальным комментарием и инкапсулированных.
Получится Core C++ Guidelines.
А потом, чтобы можно было всем этим пользоваться, добавить секцию unsafe. И получить то же, что имеем сейчас, только с unsafe {}
Новое ключевое слово не нужно, потому что есть сигнальные комментарии. А статический анализ совершенно не обязательно включать сразу со всеми проверками, можно понемногу добавлять. Ну или вообще не добавлять, если кто-то не хочет.
Главное, чтобы поддержку сети занесли.
Считаю, что поддержку многопоточности, файловой системы и сети надо было добавлять самыми первыми до синтаксических улучшений.
+1. Всё что есть в Python и C# из коробки, должно быть и в C++ из коробки.
Если бы весь этот минимум (многопоточность, ФС, сеть) сразу добавили в С++, то возможно Java и C# не появились бы :)
Да, и смешно: получается обработка одного файла (указанного в настройках программы или интерактивно пользователем), в один поток (при этом с зависанием интерфейса) и с отображением результата выполнения программы только на этом компьютере (нельзя отправить результаты по сети или сообщить о завершении работы). Попахивает 80- ыми годами :)
С++ только Qt спасает, иначе бы умер язык как не соответствующий текущим реалиям.

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

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

проблема не в том, что у всех свой строковый тип а в том, что он у всех разный. Сравните std::string, bstr_t и QString — они отличаются буквально всем. Увы, но так просто всем не угодишь.
Наличие «мелких» дублирующих типов- моя основная претензия к Qt. Например, если необходимо перебрать файлы каталога, то предварительно надо название каталога конвертировать в QString. И так практически со всеми методами библиотеки.
Зачем эти лишние телодвижения?
Ларс Кнолл на вопрос о том, когда выкинут QVector, QString и прочие велосипеды сказал, что вообще, может быть, это было бы неплохо, но планов таких нет. Имхо, было бы круто иметь Qt, в котором есть только QML/QWidgets и больше ничего.
Эй, братишка, тормозни!
А как же QRunnable + QThreadPool, которые позволяют работать на более высоком уровне задач, а не функций (как в классическом С++). Я еще там юзаю события, QReadWriteLock и файловую систему (которую пока компиляторы не реализовали).
Для этого всего есть стандартные или специализированные альтернативные реализации более высокого качества, чем в Qt.
Сразу видно знающего человека :)
А вы сомневаетесь в том, что есть инструменты предлагающие более высокие уровни абстракции, чем QRunnable+QThreadPool?
Я сомневаюсь в том, что человек говорящий загадками что- то реально знает.
А мне вот доводилось общаться с DaylightIsBurning раньше и есть ощущение, что у него просто достаточный кругозор чтобы так говорить. Если хотите примеров подобных инструментов, то это TBB, HPX, CAF, SObjectizer, FastFlow, QP. И это еще не все, что есть в C++ для parallel и concurrent computing.
Можно назвать другие более высокоуровневые инструменты, но нельзя из- за этого называть их более качественными. Ну а использование слова «стандартные» (т.е. из коробки) выдает брехуна с головой.
Ну да, ну да. Когда вы попытаетесь на QRunnable+QThreadPool изобразить что-нибудь, что в TBB или HPX доступно из коробки, слово «качественный», скорее всего, заиграет новыми красками.
Почему вы слово «высокоуровневая» подменяете словом «качественная»? Это разные понятия.
Наверное потому, что возможность распараллелить вычисления в HPX всяко качественнее, чем отсутствие оной в Qt.
Я где-то видел ваши(либо не ваши, но с со) баталии на тему многопоточности, когда решение на том же thread pool было проще и удобнее. Вы это объяснили тем, что «задача такая была». Так сразу нагуглить обсуждение не смог.

Ну и вот, если у нас такая задача, что нам хватает тредпулла, то каким образом оно стало менее качественным? Оно наоборот стало более качественным, ведь чем меньше всяких заморочек, тем меньше шансов ошибиться. И тут это слово не играет новыми красками.
Я где-то видел ваши(либо не ваши, но с со) баталии на тему многопоточности, когда решение на том же thread pool было проще и удобнее.
Возможно, речь про «обедающих философах», которые обсуждались на LOR-е.
Ну и вот, если у нас такая задача, что нам хватает тредпулла, то каким образом оно стало менее качественным?
Если под «качеством» понимать реализацию конкретно тред-пула в разных библиотеках, то может ваша точка зрения оправдана. Если под качеством понимать удобство решения задач из области parallel или concurrent computing, то более специализированный инструмент мне представляется более качественным.

Но тут, полагаю, идет спор о том, кто и как воспринял слова DaylightIsBurning, а не о том, что именно он подразумевал. Так что лучше дождаться его объяснения.
Я подразумевал оба компонента: то, что есть в Qt выглядит недостаточно featureful для законченного продукта но даже то, что реализовано уступает компактным аналогам. Да и изначальный посыл не только в том, на сколько хорошая реализация не-виджет частей в Qt, а есть ли смысл запихивать всё это в один Framework. Если я реализую компонент, в котором мне нужен несложный параллелизм, то тянуть зависимость от всего Qt даже как-то странно. Та же критика, что звучит в сорону boost, только в случае Qt она ещё острее, так как не-GUI части в Qt менее развиты чем в boost.
Тут обратная ситуация, если вы используете Qt для интерфейса, то вам не нужно интегрировать что-то стороннее для базовой многопоточности.
Я не вижу в этом преимуществ. Выходит, что я уже знаком с какой-то хорошей библиотекой многопоточности и использую в разных приложениях, но в случае использования Qt мне навязывают свой корявый велосипед, который более нигде не пригодится.
Нет не выходит, ну вот никак. Вы используете Qt для графического интерфейса и вам нужна базовая многопоточность, тогда за каким… извиняюсь, вам тянуть специализированную библиотеку, и жаловаться что «оно кривое», если ваше изначальное решение использовать для «базовой» многопоточности «специализированну» библиотеку — кривое. Если же вам нужна «не-базовая» многопоточность, то тут уже что Qt, что не Qt, а интегрировать сторонню графическую библиотеку со сторонней библиотекой многопоточности придется (если этого за вас уже не сделал кто-то другой, а в случае библиотек C++ — можете быть почти уверенны что нет).
за каким… извиняюсь, вам тянуть специализированную библиотеку
Принцип единственной ответственности. В этом вся суть программирования — брать наиболее удачные/подходящие реализации необходимых компонент (библиотеки) и комбинировать их. Задача авторов библиотек — сделать так, что бы они могли хорошо интегрироваться со сторонними библиотеками. Задача языка — предоставить для этого возможность. Разработка своих собственных уникальных и неповторимых решений для уже решенных задач — это недостаток, а не преимущество для фреймворка. Ну не могут Trolltech объять необъятное и предоставить лучшее модульное решение для всех направлений, которые Qt пытается закрыть. Раньше это было оправдано, когда альтернатив не было. Сейчас же QVector — это ненужный велосипед, который вынуждает только лишний раз морочить голову с передачей QVectror<->std::vector. Если решение от Qt не может конкурировать с альтернативами за пределами Qt приложений — скорее всего оно не нужно.
А «тянуть ещё одну библиотеку» — это вообще не проблема, если библиотека нормально организована. Тут, конечно, было бы круто иметь модули и пакетный менеджер, как в других языках типа Python или Rust.
Извините, но Вы живете в мире розовых единорогов и с реальной разработкой на C++ лично не знакомы? Какое «брать реализации необходимых компонент и комбинировать их» на C++? Это не всегда возможно даже в таких языках как C# и Java, которые проектировались с этой парадигмой. А в C++, «задачей языка — предоставлять для этого возможность» изначально не было (да и сейчас с этим — очень, не очень). Разработками своими собственными уникальными и неповторимыми решениями уже решенных задач весь Гитхаб забит (на всех языках). Извините, но вы реально витаете где-то в облаках «идеального мира программирования». Trolltech уже много лет никакого отношения к Qt не имеет, значит и о Qt вы знаете только понаслышке.
Почему это QVector ненужный велосипед, а не std::vector? В QVector, к примеру, можно настроить копирование POD элементов через системный intrinsic, а в std::vector это делается только через стандартные конструкторы копирования. И морочить голову с передачей std::vector туда-обратно не нужно, все методы уже есть в QVector, с самого его появления. Кроме того, в отличие от std::vector, QVector это не header-only класс, а значит его использование не приводит к «распуханию» результирующего кода, что актуально в больших проектах (потому как контейнеры — это базовые «кирпичики» и применяются на всех уровнях).
Trolltech уже много лет никакого отношения к Qt не имеет, значит и о Qt вы знаете только понаслышке.
Да я в курсе, что они название поменяли, но люди остались те же. Ларс Кнолл, который сейчас CTO пришел ещё в Trolltech. Так что не спешите с выводами.
А то что на практике не выходит всегда всё «по науке» это понятно, но это не повод теперь намеренно проектировать через ж.
А в C++ у вас не получится «по науке». Либо шашечки, либо ехать. Там есть такой принцип — «если вы это не используете, вы за это не платите». Это значит, что если ваша библиотека не использует, к примеру исключения, то объединить ее с другой, использующей их, будет почти невозможно и обязательно это будет получаться только через жо.. это самое. Нет, можно конечно учесть «все пожелания», но на выходе получится трудноуправляемый монстр с кучей параметров конфигурации, обмазанный макросами и шаблонами до полного FUBAR'a.
в C++ у вас не получится «по науке»
Тем не менее развития языка и библиотек представляет возможность сделать более «по науке». Qt от этого развития, на мой взгляд, по некоторым параметрам отстаёт из-за того, что продолжает тянуть «ненужные» куски. Я согласен с Вашим посылом, просто, мне кажется, за время развития Qt оптимум между «правильностью» и «практичностью» сильно сдвинулся в пользу «правильности», а Qt не везде за ним поспевает.
Ну как я писал — «либо шашечки, либо ехать». Практическая ценность Qt пока очень сильно перевешивает «академическую правильность» стандартной библиотеки, в области десктопных приложений :-).
Да, но только за счёт того, GUI части Qt. В плане GUI у Qt нет серьезных библиотек-конкурентов и можно потерпеть технологическое отставание в о стальном. Если бы был форк QtWidgets/QML без всего остального — мне кажется он был бы ещё предпочтительней чем Qt. На мой взгляд в тех частях, где std и Qt реализуют одно и то же, std выигрывает и по практичности и по «правильности» архитектуры. И это при том, что std в этом плане не всегда является лучшим доступным вариантом.
Это значит, что если ваша библиотека не использует, к примеру исключения, то объединить ее с другой, использующей их, будет почти невозможно и обязательно это будет получаться только через жо… это самое

почитайте про паттерн «адаптер»
Есть две библиотеки, одна — исключения бросает, вторая — коды ошибок возвращает. Вам они нужны. Но они бинарно несовместимы. Помните, «если вы это не используете, вы за это не платите»? Поэтому «адаптер» вам не поможет, там все не так просто. Здесь вовлечены такие вещи как «отвинчивание» стека и деструкторы. Вам придется копировать данные между этими библиотеками вручную, а если там еще и обратные вызовы нужны… Короче, вам придется целую третью библиотеку для этого написать и на месяц «загулять» в отладке.
Почему это QVector ненужный велосипед, а не std::vector?

как минимум потому, что у QVector'а v[i] = 0; может выполняться линейное время. Он был хорош до с++11, но не после введения move-семантики
А может и не выполнятся за линейное время; так себе аргумент. Qt это единственная библиотека GUI на C++ имеющая полный набор необходимый возможностей. То что она не использует контейнеры STL, трудно назвать недостатком. Ну допустим применялась бы в Qt стандартная библиотека. Это бы хоть-как то помогло с интеграцией ее с другой сторонней библиотекой, также использующей стандартную библиотеку C++? Практика показывает что нет. А семантика перемещения, это свойство самого языка и контейнеры Qt тоже смогут ее применять; некоторые методы ее уже используют.
Это бы хоть-как то помогло с интеграцией ее с другой сторонней библиотекой, также использующей стандартную библиотеку C++?
Да, библиотека стала бы меньше при этом нужная функциональность всё равно есть в std и ко. Интерфейсы с другим кодом упрощаются, не нужно вечно на каждый std::string городить QString::fromStdString() и т.п. К тому же работа c Qt для программистов упростилась бы — не нужно вникать в особенности Qt-шных альтернатив. Одно только засилье сырых указателей и сопутствующих приблуд чего стоит.
Библиотека стала бы меньше, а создаваемый код — больше, именно из-за того что STL-контейнеры — это header-only, что ведет к «распуханию» скомпилированного кода (особенно в больших проектах не сводящихся к одному исполняемому файлу). Мне нравится в контейнерах Qt то что у них есть не-шаблонная основа, которая не будет каждый раз разворачиваться вместе с шаблоном. И, да, интерфейсы конечно же упростились бы на пару строк. Но, на практике, чаще нужен интерфейс с библиотекой С, а не С++. А, извиняюсь, где вы в Qt засилье сырых указателей увидели? Одним из плюсов Qt, в плане разработки, как раз и является избавление от большей части ручного управления памятью. Как пример, тот же std::string, рано или поздно вам придется передавать его по указателю чтобы избавится от копирования данных, ссылок (даже с учетом новой семантики перемещения) надолго не хватит. QString, с другой стороны, является по сути указателем семантики COW (copy-on-write) на строку, завернутым в класс, и передача его по значению грозит только накладными расходами на счетчик ссылок (который у вас тоже появится, если вы все же откажетесь от ручного управления std::string* и перейдете на std::shared_ptr).
вот как раз тот факт, что «вот здесь накладные расходы на счетчик ссылок, вот здесь — на detach, вот здесь — на +1 уровень индирекции и т.д.» и мешает контейнерам Qt быть лучше STL-ных. Плюс к тому, COW усложняет отслеживание инвалидации итераторов и нарушает гарантии алгоритмической сложности базовых операций. На практике там, где строку надо копировать (для изменения), вы её будете копировать и с COW, и без него. А там где не надо -достаточно мува или ссылки. Так а если нет разницы, зачем платить больше?
А как же разворачивание шаблонов? STL генерирует много дублирующего кода. Его оптимизация нигде не стандартизирована, а в случае с динамическими библиотеками — невозможна. Использовать стандартные контейнеры без указателей на них возможно только в примерах. На практике, вы будете заворачивать их в смарт-указатели («вот здесь накладные расходы на счетчик ссылок») либо управлять памятью вручную (огромный привет отладчику). Это уже — "+1 уровень индирекции". Там где строку надо копировать для изменения, это очень не факт что вы не забудете ее скопировать, ошибка «алиасинга» данных не просто так одна из самых распространенных в программировании. Если придерживаться правил (не изменять контейнеры в цикле вне итераторов, не разыменовывать нулевые указатели и т.п.) и следовать шаблонам использования Qt, сложностей не возникает. Опять же, следуя правилам и шаблонам у вас не возникнет ситуации с нарушением гарантии алгоритмической сложности операций. Но да, в некоторых случаях в STL меньше накладных расходов чем в Qt, хотя упрощение процесса разработки сильно перевешивает, по крайней мере, для меня. STL не избавляет вас от ручного управления памятью, так что платить вы будете в итоге столько же если не больше, чем в Qt. Qt здесь «срезает углы», беря не себя больше управления памятью чем STL, для меня это плюс. Если для вас это минус, возможно вы просто мало кода на С++ писали.
А как же разворачивание шаблонов? STL генерирует много дублирующего кода.

Но да, в некоторых случаях в STL меньше накладных расходов чем в Qt, хотя упрощение процесса разработки сильно перевешивает, по крайней мере, для меня

Во-первых, невозможно STL-ем надублировать больше шаблонного кода, чем весит даже базовый комплект Qt. Во-вторых, Qt генерирует много шаблонного кода для метаобъектной информации.
В-третьих, накладные расходы Qt'а вам в радость, а STL «код раздувает». Как будто QVector/etc. не генерируют шаблонный код…
Там где строку надо копировать для изменения, это очень не факт что вы не забудете ее скопировать, ошибка «алиасинга» данных не просто так одна из самых распространенных в программировании.

Как можно «забыть скопировать строку для изменения», переданную по const &?
Использовать стандартные контейнеры без указателей на них возможно только в примерах

Как-то не доводилось работать с контейнерами по указателям, хоть сырыми, хоть умными. Только по ссылкам. Возможно, вы просто мало хорошего кода на с++ писали?
Во-первых, невозможно STL-ем создавать десктопные приложения с GUI. Во-вторых, Qt генерирует не дублирующийся код для мета-информации, и только если вы создаете типы с мета-информацией. В-третьих, накладные расходы Qt, это плата за управление памятью за вас (я не хочу тратить время на тривиальные решения по управлению памятью, хоть это и даст мне 10-15% производительности, а в нагрузку еще дополнительное времени на отладку и сопровождение этих решений). STL «раздувает» код там где это совершенно не обязательно — если у вас много типов одинакового размера, вся информация о типах пропадает после компиляции, и код контейнеров не будет различаться даже размерами смещений. Или если один и тот же шаблон в разных исполняемых файлах и/или динамических библиотеках, то это просто дублирование одинакового кода. Я не говорю что это так для всех реализаций STL, существуют реализации где есть не-шаблонная основа (подобно Qt), но сколько компиляторов, столько и реализаций (это кстати тоже было минусом, когда разные реализации стандартной библиотеке были разной степени «стандартности»).

Забыть скопировать строку можно если она не передана по const&, а сидит в структуре данных по указателю. А как вы работаете со сложными структурами данных без указателей? Пересоздаете всю структуру если нужно заменить один объект на который она ссылается? Нет, можно писать программы и без указателей и даже без единого побочного эффекта, но зачем для этого использовать C++?
Или если один и тот же шаблон в разных исполняемых файлах и/или динамических библиотеках, то это просто дублирование одинакового кода.

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

Допустим, я умею передавать объекты не только по значению, но и по различного вида ссылкам. Зачем мне COW?
как вы работаете со сложными структурами данных без указателей? Пересоздаете всю структуру если нужно заменить один объект на который она ссылается?

Если я ссылаюсь на один элемент контейнера, я беру ссылку на него. Необходимости хранить эту ссылку обычно нет.
Вроде шаблоны классов с фейковыми параметрами использовали для оптимизации размера: C++ компоновщик удаляет из результирующего образа не используемые методы инстанциированных классов-шаблонов и оставляет только один экземпляр инстанциации из созданных в разных единицах компиляции. Разве не так? К распуханию кода от header-only приводит а)чрезмерное увлечение инлайном и б)инстанциации для многих типов. При этом, теоретически, для всех контейнеров, работающих с unique_ptr или с T* в финальном образе должна быть одна копия, но это зависит от правильности и полноты реализации шаблонных контейнеров и компилятора. Но однозначно говорить, что использование stl ведет к распуханию из-за дублирующего кода — слишком на мой вкус смело. Скорее, к такому результату ведет бездумное использование stl.
Тут проблем несколько, если у вас не один исполняемый файл, а много и/или динамические библиотеки, то тут избежать дублирования невозможно. Во вторых если у вас много типов одинакового размера, то результирующий машинный код по-сути будет различаться только константами размеров и смещений, тут тоже даже в одной единице компиляции будет по сути одинаковый код. Это проблема всех header-only шаблонов. Тот же QVector отличается от std::vector тем что в QVector есть не-шаблонная основа, работающая с void-указателями и байтовыми размерами, а сам QVector — это шаблонная обёртка дающая безопасность типов. И при развертывании от нее остаются только размеры типов и смещения. Но QVector «тяжелее» std::vector в том что он добавляет еще механизм copy-on-write и ведет себя как объект, которое можно передавать по значению без фактического копирования содержимого, хотя на самом деле копирование просто откладывается до первой модификации содержимого.
Спорить о преимуществах и недостатках подхода с единым исполнимым файлом или выделения частей программы в разделяемые библиотеки можно до бесконечности. Замечу лишь, что последние годы реальных причин для сборки своего кода в динамическую библиотеку встречаю все меньше…
Qt это единственная библиотека GUI на C++ имеющая полный набор необходимый возможностей. То что она не использует контейнеры STL, трудно назвать недостатком.

а теперь возьмите напишите библиотеку на Qt и попробуйте её распространить для использования в приложениях с и без Qt. Без открытия исходного кода. И вам пользователи быстро объяснят где же вы не правы.
Каким образом фраза «а теперь возьмите напишите библиотеку на Qt и попробуйте её распространить...» соотносится с моим утверждением, что «Qt это единственная библиотека GUI на С++ имеющая полный набор необходимых возможностей»? Я не понял что вы хотели сказать.
я хотел сказать, что использование этого «полного набора возможностей» может лишь навредить вашему приложению.
Как наличие, условно, 25 виджетов вместо 10, может навредить? Или поддержка этими виджетами многопоточности? Или интегрированная с этими виджетами библиотека мультимедиа? Извините, я вас не понимаю.
потому что не хотите понимать. 90% функционала Qt завязано на их реализации QThread + QCoreApplication. А теперь внимание: при попытке инстанцировать QCoreApplication дважды (в либе и в приложении) или ни разу ничего работать не будет. То же самое, если версия Qt либы не совпадает с версией приложения. Поэтому большая часть Qt-библиотек либо распространяется в виде исходников, либо идет вместе с Qt.
Код, которому нужны потоки использует реализацию многопоточности, неужели это вас удивляет? Если вам не нужен функционал Qt, вы вообще не используете Qt, в чем проблема? Qt поддерживает ститическую компоновку (как и любая библиотека C++), это если вас смущает необходимость тащить всю DLL. Любая релизация стандартной библиотеки C++ (та что не header-only) ровно также ломается если приложение собиралось с другой версией. Это общая проблема бинарной совместимости вообще любой библиотеки C++. Любое приложение на C++ под Windows поставляется вместе с msvcrt, потому что 99% функционала завязано на стандартной библиотеке.
QtCore, в которой «лежит» реализация многопоточности, используется всеми другими модулями Qt
использование слова «стандартные» (т.е. из коробки) выдает брехуна с головой.
работать на более высоком уровне задач, а не функций
en.cppreference.com/w/cpp/thread/packaged_task, к примеру.
Не надо хамить. Если Ваше мнение не совпадает с моим или ответ показался Вам неполным — это ещё не значит, что можно делать те поверхностные выводы, которые Вы спешите делать.
НЛО прилетело и опубликовало эту надпись здесь
Всё верно, но стоит ли горевать, если всё заменят на аналоги? Почему не воспользоваться чем-то готовым? Есть же std::packaged_task, boost и множество других реализаций. Другие реализации хотя бы можно применять в не-Qt проектах и, в случае потребности, для более сложных задач связанных с параллелизмом.
НЛО прилетело и опубликовало эту надпись здесь
ломать голову, как скрестить буст с QEventLoop
Ну я предполагаю, что разработчики Qt об этом позаботятся и, выкинув свои велосипеды, сделают удобную поддержку чего-то другого (стандартного, например). Это и есть изначальный посыл: в Qt, кроме GUI нет ничего стоящего по современным меркам, так не лучше ли выкинуть велосипеды и сделать, где надо, интеграцию с внешними либами.
сложность от необходимости изучения нескольких API с лёгкостью покрывается сложностью написания многопоточного кода вообще.
Согласен.
НЛО прилетело и опубликовало эту надпись здесь
Ценят, но ломают переодически и довольно регулярно депрекейтят. Qt3/4 всё поломали, Qt4/5 в основном старые API сохранили, но не все, к тому же по ходу развития пятой версии многое из старого задепрекейтили. Я тоже не думаю, что выкинут (хотя к 6й версии могли бы), но не потому, что ценят совместимость, а потому что это требует усилий, жалко и NIH.
Что Вы, я вовсе не собирался говорить загадками, мне показалось, что моё утверждение тривиально и не вызовет споров, потому и не стал вдаваться в подробности, лишь обозначил направление.
Я сомневаюсь в том, что человек говорящий загадками что- то реально знает.
Не вам судить. Так-то Вы вообще компилятор и стандартную библиотеку путаете:
файловую систему (которую пока компиляторы не реализовали)
Если честно, я не думал, что кто-то будет оспаривать то, что библиотека примитивов параллелизма в Qt не воспринимается сегодня как серьезное решение. На мой взгляд, этот компонент добавлен в Qt по принципу «добавим что-то по-минимуму что бы покрыть базовые потребности». Подобный уровень проработки направления характерен скорее для single-header libraries, например. Точно также как, к примеру, существует QJsonDocument, который ни в чём не превосходит rapidjson и другие аналогичные решения. Удивлён, что кто-то всерьез стал защищать Qt как библиотеку для параллелизма. eao197 привёл вам кучу примеров полнофункциональных библиотек параллельных алгоритмов. На мой взгляд сравнивать их с Qt даже не совсем уместно также как QPoint не тянет на сравнение с библиотеками для линейной алгебры. Возможности Qt не дотягивают даже до asyncplusplus, ThreadPool или CTPL
НЛО прилетело и опубликовало эту надпись здесь
И почему это важно? Какие в этом существенные преимущества? Сейчас наоборот многие избегают буст, говорят что он «too general to be useful» и переходят на небольшие специализированные библиотеки с одной функцией.
НЛО прилетело и опубликовало эту надпись здесь
Qt для другого — это скорее как новый, более простой и медленный язык на базе с++, под определенный класс задач. Буст то хоть можно использовать маленькими кусками.
C++ для другого — это скорее как новый, более простой и медленный язык на базе C, под определенный класс задач. Макросы то хоть можно использовать маленькими кусками.
Вы совсем не понимаете, что такое Qt.
4 года пользовался не понимая чем, значит? ;)
Вы надеюсь в курсе, что весь Qt потихоньку перетекает в QML, который буквально является другим языком?
Никуда Qt не перетекает.
Современный интерфейс требует программирования (а не набрасывания элементов на форму), чтобы можно было его программно менять. Только поэтому внедрили QML. Ничего более, чем реализовать интерфейс на QML нельзя.
вы явно не следите за развитием Qt. Некоторые модули (например, QtLocation) даже не имеют полноценного c++ API. И да, Qt всегда предназначался в первую очередь как универсальный GUI-framework.
Зачем ты ерунду пишешь? Если писал на Qt, то должен понимать, что несешь полнейшую дичь. Зачем?
Qt действительно всегда предназначался в первую очередь как универсальный GUI-framework, но на «новый медленный язык» это не тянет. Разработка с Qt не больше отличается от разработки от разработки на C++, чем в случае других библиотек. Конечно, любая библиотека накладывает свои особенности, но что бы прямо другой язык, да ещё и медленный. Разработка под Qt сама по себе совершенно не подразумевает низкой производительности.
QML — да, но это же не весь Qt, к моему сожалению.
Ничего себе «особенности» — slots and signals…
slots and signals — это слегка допиленные callbacks
Да?! А на мой вкус это макросы, скверно замаскированные уродливой кодогенерацией. Но, как говорится, на вкус и цвет…
Да, slots and signals — это callbacks, реализованные через макросы и moc. Тем не менее, подход slots and signals не так уж значительно отличается от подходов применяющих коллбеки и соотв. не может считаться «новым языком». C++ с коллбеками же не считается отдельным языком.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
Критика в том, что у многих из компонент буста есть более приятные аналоги, не только property_tree. Например pybind11 куда приятнее boost::python. Слышал, что от Spirit тоже многие отказываются в пользу специализированных библиотек — ради удобства и производительности.
НЛО прилетело и опубликовало эту надпись здесь
Я к тому, что для таких примитивов как строки как-то ожидаешь наличия более-менее нормального решения для повседневной работы (варианты многомегабайтных строк загружаемых отображением в память оставим), и если кто предложит не добавлять строки в язык, первое возражение, которое приходит на ум: «так ведь тогда подключение пяти библиотек потянет 4 разных реализации строк». А потом смотришь на C++, вроде строки есть, неплохие, ан нет, всё равно подключение нескольких библиотек приводит к конвертации строк между форматами.
А теперь представьте, что было бы, если бы в C++98 добавили, ну например, асинхронный IO, примерно соответствующий возможностям select из POSIX. Каковы шансы на то что он угодил бы хотя бы той же доле, которой угодил std::string?
НЛО прилетело и опубликовало эту надпись здесь
А чем плохо иметь аналог pip для C++? Я бы совсем не отказался.
НЛО прилетело и опубликовало эту надпись здесь
А какие сущности для C++ в этом плане уже есть? Ну, если аналог pip-а в C++ не нужен.
НЛО прилетело и опубликовало эту надпись здесь
для чего С++ менеджер пакетов?
Чтобы быстро собрать нужные библиотеки без огладки на ОС. Почему в мире Python, Ruby, Java и Rust-а это делается «по щелчку», а в мире C++ — нет?
что бы каждую либо вынести отдельно?
Как будто в этом есть что-то плохое.
НЛО прилетело и опубликовало эту надпись здесь
вы предлагаете пакетный менеджер и для С++ что бы так страдать?
Я не понял причины ваших страданий и не понял, почему вы страдания из Python-а пытаетесь перенести на C++.

Мне, например, неудобно, что под Ubuntu нужно подключать зависимости через apt, на Arch-е через pacman, на FreeBSD через pkg, а под Windows через vcpkg. Хочется что-то хорошее, вроде Rust-овского Cargo, чтобы не было привязки к пакетным менеджерам конкретных ОС.
если разобрать весь std на отдельные либы по хидерам
Не нужно дробить std. А вот возможность подключать к себе чужие библиотеки через простое описание зависимостей — это очень ценно и удобно.
Только вот раст не использует системные библиотеки, а всё тащит с собой. Так же у раста: один компилятор, статическая линковка, одна система сборки и никакоголегаси кода.

Если С++-проект существует в таких же условиях(в которых существует раст-проект), то никаких особых проблем не возникает, особенно в контексте тех же header-only зависимостей. Носим зависимости с собой, либо живые по субмодулям.

Какую-то значительную часть кода всё равно не перевести на новые рельсы, особенно учитывая то, что в мире С++ очень много системных сишных зависимостей.

Будут только новые заморочки с сомнительной полезностью.
то никаких особых проблем не возникает
Сказки только не нужно рассказывать. Приходится либо возможности VCS использовать, либо делать свои велосипеды для того, чтобы подтаскивать зависимости одинаковым образом вне зависимости от платформы.
Сказки только не нужно рассказывать.

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

Приходится либо возможности VCS использовать

Это какая-то проблема? Или это нельзя использовать? Чем установка на таргет vcs отличается от установки cargo? Ничем? А использовать надо что-то в любом случае.

Расскажи о возможных проблем в ситуации той, которую я выше описал.
Простите, но вы ничего не описали. Конкретики не было. Но если хотите показать, насколько все хорошо, то расскажите, как организовать управление зависимостями для кросс-платформенного проекта, который должен использовать, скажем, Boost (MultiIndex, Spirit), ACE, Catch и spdlog.
Boost (MultiIndex, Spirit), Catch и spdlog.

Всё это есть на гитхабе. Добавляем их в субмодули, закинув в какое-нибудь third_party, указывая нужную ветку. Далее забиваем пути к инклюдам каждого пакета в компилятор руками. Обычно через cmake.

С ACE будет сложнее, но это проблемы ace и пакетный менеджер ей никак уже не поможет. Это просто дремучие легаси. Еслиб это был какой-нибудь standalone asio, то никаких проблем не возникает(так же, как и со всем, что выше).

Всё это есть на гитхабе. Добавляем их в субмодули
А вот вы попробуйте. Я попробовал взять Boost.Interprocess и нужные ему зависимости. Оказалось, что вытащить цепочку нужных частей Boost-а непросто. И даже специально разработанная для этого утилита не всегда точна.

Так что потрындеть на форуме, так все в шоколаде. А когда до дела доходит, то начинается геморрой. От которого вы предпочитаете отмахиваться фразами вроде «Это просто дремучие легаси».
А вот вы попробуйте.

Пробовал, не волнуйтесь.

Я попробовал взять Boost.Interprocess и нужные ему зависимости. Оказалось, что вытащить цепочку нужных частей Boost-а непросто.

Не вижу смысла тащить нужное, там всё равно утащится пол буста.

Делается за минуту pastebin.com/raw/mTsJ87hA без всяких проблем. Первый попавшийся пример успешно собирается.

И даже специально разработанная для этого утилита не всегда точна.

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

Так что потрындеть на форуме

Вы мне дали список, я вам сообщил, что никаких проблем нет. Вы начали ссылаться именно на «потрындеть», обвиняя меня в том же самом. Какой в этом смысл?

А когда до дела доходит, то начинается геморрой.

Геморрой приходит потому, что изначально что-то используется не так, и что самое интересное, разговор был не об этом. Если упомянутое вами ACE не ушло с gnumake до сих пор, то ни на какое «карго» они не перейдут.

Тоже самое и c бустом, проблема организации буста — проблема буста. Да, придётся потратить( один раз) на пару минут больше времени, чем с нормальной автономной ho библитекой, но опять же — это не проблема.

От которого вы предпочитаете отмахиваться фразами вроде «Это просто дремучие легаси».

Естественно, а иначе никак. У вас нет вариантов. В расте нет дремучего легаси и каждый пакет сам отвечает за себя. И если ваш легаси-проект не может уйти от легаси, то ни в какой пакетный менеджер он не уйдёт. Это очевидно.

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

Вам нужно учитывать контекст, вы должны показать и рассказать, каким образом при создании для C++ cargo ACE уйдёт на карго. Какое у вас основание так думать? Ничего к этому не располагает.

А забыть о контексте, о ваших же примерах и потом крыть «ну дак проблемы бывают» — бывают, везде. И вопрос не в самих проблем, а в том решении(карго), что предлагаете вы. Вам нужно не просто обвинить моё решение, но и показать то, каким образом ВАШЕ решение это обойдёт. Это очевидно.

Пробовал, не волнуйтесь.
Волнуюсь, поскольку сомневаюсь, что пробовали.
Не вижу смысла тащить нужное, там всё равно утащится пол буста.
25 библиотек — это не полбуста, это меньше четверти. Ну и если вы не видите смысла, это не значит, что все согласны с вашими взглядами.
Точности всегда можно добавить руками, это нужно сделать один раз.
В этом и фокус: каждому разработчику это нужно будет делать, минимум, один раз для каждого своего проекта. Это непродуктивно.
Вы мне дали список, я вам сообщил, что никаких проблем нет.
«Я вам сообщил» — это теперь такая форма доказательства? Не срабатывает.
И если ваш легаси-проект не может уйти от легаси, то ни в какой пакетный менеджер он не уйдёт. Это очевидно.
Для вас может быть и очевидно. А вот опыт vcpkg показывает, что не очевидно. Порты vcpkg можно делать даже для библиотек, которые про vckpg ничего не знают.
Вам нужно учитывать контекст, вы должны показать и рассказать, каким образом при создании для C++ cargo ACE уйдёт на карго.
Вот прямо таки должен? :))) Вы что-то путаете. Есть много людей, которые находят неудобным отсутствие менеджера зависимостей в C++. Я думаю, что ваш совет управлять зависимостями через git submodules они проигнорируют, а вот что-то из vcpkg/conan/hunter попробуют.
Это очевидно.
Очевидно, что вы заблудились в словах. Проблема в том, что в C++ нет ничего подобного на Cargo/Maven/RubyGems. И вторая проблема в том, что есть персонажи (вы среди них), которые считают, что это не проблема.

Хорошо бы сперва прийти к тому, что отсутствие штатного (де-факто стандартного) менеджера зависимостей для C++ это проблема. В этом я и хочу убедить собеседников. А вовсе не в том, что именно Cargo нужен C++.
25 библиотек — это не полбуста, это меньше четверти. Ну и если вы не видите смысла, это не значит, что все согласны с вашими взглядами.

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

В этом и фокус: каждому разработчику это нужно будет делать, минимум, один раз для каждого своего проекта. Это непродуктивно.

Нужно делать что? Заполнять зависимости вы будите в любом случае, никакой разницы нет.

А далее вы опять игнорируете неудобные моменты. Вы рассказывали о какой-то сложность, каких-то проблемах и я вам показал, что это решается за 1минуту. Максимум за 5. Т.е. никаких проблем нет. Ваши претензии были необоснованными, а раз уже есть прецедент, то всё остальное я могу записать туда же, пока вы не докажете обратное.

Кстати, расскажи, сколько у вас проектов? Если 5минут для вас проблема, то их должны быть десятки, сотни в день. Что очень сомнительно, и эти сомнения вы не развеяли.

«Я вам сообщил» — это теперь такая форма доказательства? Не срабатывает.

Я ничего кроме сообщений от вас не вижу, в чём смысл меня обвинять, если делаете тоже самое?

При этом, я уже вам отвечал и даже показывал как. Вы же ничего не показывали, ничего не ответили, а просто сей факт проигнорировали.

Для вас может быть и очевидно. А вот опыт vcpkg показывает, что не очевидно. Порты vcpkg можно делать даже для библиотек, которые про vckpg ничего не знают.

Вы сами будите поддерживать эти порты? Зачем вы говорили о карго? У вас каждую секунду появляется новое обстоятельство. Вы уже перевели ace на нормальную систему сборки, либо кто-либо другой? Нет, дак какой может быть разговор?

Так что потрындеть на форуме, так все в шоколаде. А когда до дела доходит, то начинается геморрой. От которого вы предпочитаете отмахиваться фразами вроде «всё сработает».


Вот прямо таки должен? :))) Вы что-то путаете.

Не путаю, если не должны «потрындеть на форум», а вот «не потрындеть» должны.

Есть много людей, которые находят неудобным отсутствие менеджера зависимостей в C++.

Дальше что? Мы обсуждаем ваши, либо чьи-либо рассуждения об удобстве. Мы обсуждаем именно то, что в современных реалиях нет никаких проблем. Вы утверждали обратное, пока безуспешно.

Я думаю, что ваш совет управлять зависимостями через git submodules они проигнорируют, а вот что-то из vcpkg/conan/hunter попробуют.

И флаг им в руки, дальше то что?

Очевидно, что вы заблудились в словах.

Заблудились именно вы.

Проблема в том, что в C++ нет ничего подобного на Cargo/Maven/RubyGems.

И вам сообщили о том, что никто подобного быть в принципе не может т.к. мир С++ состоит из легаси, именно у легаси проблемы с дистрибуцией и сборкой. И именно им и нужен пакетный менеджер. Но они на него не пойдут, т.к. если бы хотели — уже бы ушли хотя-бы с gnumake, а пока это трындёж на форуме.

И вторая проблема в том, что есть персонажи (вы среди них), которые считают, что это не проблема.

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

Те, кому это интересно — уже давно на standalone ho, т.е. они пытаются решить и решают проблемы. Вы же её не решаете и решать не пытаетесь, а все ваши рассуждения сводятся к тому, что «вот дадут нам официальный ПМ — весь код сразу на нём будет». Чем это обосновано? Никто не знает.

К тому же, я не только считаю, но и показываю почему. Вы начали про Boost.Interprocess, и вам оказалось сложно. Но мне почему-то оказалось не сложно. Может всё же ваше «сложно» не очень объективно?

Хорошо бы сперва прийти к тому, что отсутствие штатного (де-факто стандартного) менеджера зависимостей для C++ это проблема.

Это абсолютно неважно. Важно то, что его наличие ничего не изменит. Для тех, кто использует беспроблемные техники — ничего не изменится. Для тех, кто использует проблемные — так же, ведь основная причина их проблемы в том, что они легаси. Если легаси уже 20лет как легаси, то никакой новый, модный ПМ им не поможет.

В этом я и хочу убедить собеседников. А вовсе не в том, что именно Cargo нужен C++.

Вы не понимаете простой вещи. В языка с ПМ есть не ПМ, а нечто иное. Он там был всегда. В рамках МП мыслят создатели библиотек, пользователи библиотек. Это не просто МП — это система дистрибуции. Для компилируемых языков — это ещё и система сборки. Очередной МП вам не даст того же, что даёт карго.

И даже если у нас появится этот самый ПМ — никакое легаси на него не переберётся. Рассчитывать неких волонтёров не приходится. Не нужно сравнивать с vcpkg и прочим — это просто набор скриптов поверх базовой системы сборки, который не даст той просты, той унификации, которую даёт cargo и ему подобные.

Сколько лет уже буст пытаются перевести на cmake? Много. Кто-то левый возьмётся это делать? Сомневаюсь.

Вот и получится так, как получилось со всеми левыми ПМ. То, что уже нормально работает туда добавили, а все сложные легаси вещи, с которыми и существуют основные проблемы — нет. И магическое слово «стандартный» мало что изменит.

Вы мне очень напоминаете одного персонажа с LOR-а, посему беседу с вами следует закончить.
Ваши неудачи всегда вам кого-то напоминают? Удобно. По существу вам ответить нечего, посему беседу с вами следует закончить, процитировав ваше:

Так что потрындеть на форуме. А когда до дела доходит,

Дело доходит и тут же кончается, а трындёж остаётся.
Я прошу прощения, что вмешиваюсь в разговор не своего уровня (пока что), но Ваша позиция напоминает поговорку «не жили богато, нечего и начинать».
Вы говорите, что мир С++ состоит из легаси, легаси не будет использовать новую стандартную систему дистрибуции, а значит не нужно её создавать. Я думаю, такая позиция будет откровенно вредной для людей, которые занимаются разработкой и внедрением новых фич в С++ с целью его развивать и улучшать, а не готовить к постепенной деградации.
Да, какое-то легаси будет переводиться на новую систему дистрибуции дольше, чем выходит HL3, но почему это должно влиять на новые проекты?
Старые проекты будут или не будут использовать новый ПМ в зависимости от соотношения профит/трудозатраты, а создатели новых проектов будут «мыслить в рамках нового МП». Если систему модулей, менеджер пакетов и реппозиторий пакетов смогут внедрить придерживаясь принципа «не платишь за то, что не используешь», то в этом со всех сторон будет одна лишь польза. Разве не так?
Ваша позиция напоминает поговорку «не жили богато, нечего и начинать».

У вас очень странные представления. Лично я считаю, что это новое — это деградация.

Я выше писал, но повторю более полно. С выкидыванием такого понятия как cpp-файл — решаются все проблемы. Со сборкой, с линковкой, с дистрибуцией зависимостей, с переносимостью. Выше я всё это разбирал.

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

Сейчас нам предлагают модули. Да, они лучше легаси-подхода, но лучше ли они инклюдов? Я не вижу, не вижу в чём лучше. Вижу только хуже. Инклюды обладают полной прозрачностью:

Они существуют на уровне языка( в отличии от всех внешних приключений в случаи раздельной сборки).

Они позволяют получить/изучить/модифицировать код. Вам не нужно изучать внешние костыли и заморочки каждого конкретного проекта — всё тут, всё в общем виде.

И это только начало. Пунктов ещё много. Модули опять откатят нас в 80е года, но сейчас у нас есть надежда — ide, которая нам будет эмулировать инклюды.

Пакетный менеджер — он всё равно нам ничего не заменит. У нас есть система для хранения/дистрибуции кода — гитхаб и иже с ним. Нам нужна будет vcs, она у нас есть. Опять же, есть гитхаб для работы с vcs. У нас есть всё.

Система сборки в полной мере не нужна. Она остаётся как костыли для решения всяких платформозависимых проблем, но мы уже давно пытаемся от них уйти.

И что же нам действительно нужно? Нам нужны альтернативы костылей на макросах. Сбора информации о системе, условная компиляция.

Люди пытаются пропихнуть модули, рассказывая о плохих макросах, но. Кто-то дал людям до модулей альтернативу? Какие-то минимальные подвижки есть — тот же порядок байт и прочее, но это лишь крохи.

Модули не дадут никакого разительного преимущества по части времени компиляции, по части упрощения разбора кода. Есть подвижки в сторону действительно революционной вещи — инкрементальной сборки? Которая даст невероятный буст. Нужны компиляторы-сервисы, которые будут жить постоянно, постоянно инкрементально пересобирая программу.

И тут уже будут инклюды, тут уже не будут нужны никакие системы ускоряющие сборку/следящие за обновлением файлов, никакие модули. Я вижу в этом прогресс, а не в модулях/МП«х и прочем, что ничего по сути не даст, а только откатит нас назад.

не платишь за то, что не используешь

Платишь. Ресурсы людей не безграничны. К тому же, модули никогда не будут так же удобны и прозрачны как инклюды.

Хм, ну почти все Ваши аргументы, в принципе, выглядят логично. Насчёт удобства наличия пакетного менеджера, наверно, можно поспорить, но незачем, т.к., насколько я понял, он вполне себе нормально может работать и с header only либами с инклюдами.

В общем, спасибо что подробно всё расписали. Есть над чем подумать.
Менеджер пакетом это удобно тогда, когда он есть и он унифицирует всю работу с проектом. Когда любую зависимость/программу берёшь и используешь. В ситуации же с С++ такого не будет, в ближайшей перспективе точно.

Никто(в частности я) не спорит с тем, что это удобно. Я просто не вижу вариантов в которых он внесёт какие-то заметные изменения в реалии, в частности мои. Слишком много нужно сделать, причём с очень сомнительным профитом. В этом моя претензия.

К тому же, я просто не представляю как в С++ мире может существовать какай-то аналог карго. У всех языком с ПМ зачастую один единственный тулчейн. Питон, жава, жс, раст. Да, там есть какие-то альтерантивы, но они очень нишевые и их 1-3 штуки. Как это вообще должно работать во всём это зоопарке — решительно непонятно.

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

1. Подтащить нужные вам зависимости. Например, вам нужна библиотека A версии 1.2.3 и библиотека B версии 2.3.4. А так же все их зависимости. Желательно с проверкой конфликтов (скажем, если A зависит от G версии 3.4.5, а B — от G версии 2.8.9, причем G-3.4.5 не совместимы с G-2.8.9).

2. Сборка всего этого хозяйства.

Один подход состоит в том, чтобы пытаться увязать это все вместе. Например, vcpkg и (насколько я знаю) hunter требуют поддержки CMake от проектов. С помощью vcpkg/hunter вы вытаскиваете зависимости и эти зависимости становятся вам доступны без лишних усилий, если вы используете в своем проекте CMake. По аналогичному пути пошли разработчики build2. Там вообще все в одном флаконе — и зависимости, и сборка.

Другой подход состоит в том, чтобы разделись управление зависимостями и сборку. По этому пути сейчас идет conan, который, как и его предшественник, biicode был изначально привязан к CMake, но сейчас это уже (вроде как) не обязательно.

Моя точка зрения состоит в том, что два эти вопроса нужно рассматривать раздельно. По крайней мере сейчас.

В вопросе системы сборки в настоящее время прослеживается явная тенденция к тому, чтобы де-факто стандартом стал CMake. По большому счету, новые проекты изначально стараются поддерживать CMake, старые потихоньку адаптируются под CMake или же CMake-файлы для них делают те, кто вынужден использовать старые проекты. Тенденция достаточно заметная и устойчивая, активно поддерживается производителями самых заметных IDE. Так что со временем вопроса как собрать проект X не будет — если этот проект более-менее жив, то для него где-то будет CMake-файл.

А вот с вопросом описания и подтаскивания зависимостей не так все просто. Но вот vcpkg показал, что port-файл для проекта X можно создать даже не вмешиваясь в сам проект X. Правда, при этом у vcpkg есть странные родовые травмы, которые вызывают сомнения в перспективности самого vcpkg. Но вот то, что в vcpkg можно засунуть любой проект, для которого доступен тарболл — это знаковый показатель.

Причем, в вопросах управления зависимостями нужно различать несколько аспектов. Во-первых, собственно, сам транспорт. Где будут складироваться пакеты, как они будут доставляться? Во-вторых, расположение загруженных пакетов — внутри вашего рабочего каталога, снаружи. Должен ли однажды загруженный пакет быть доступен любым вашим проектам на этой машине. Или же он должен принадлежать только одному вашему проекту.

В зависимости от ответов на эти вопросы можно выбирать и инструментарий для реализации управления зависимостями. Скажем, озвученный выше подход с git submodules вполне себе будет рабочим в определенных условиях. Как-то: вы работаете с git-ом (а не с другой vcs), ваши зависимости должны принадлежать только одному вашему проекту.

Но если вы хотите, чтобы однажды загруженный boost-1.67 был доступен всем вашим проектам на конкретной машине, то нужен какой-то другой подход.

Как раз эти подходы сейчас и исследуются в рамках разных инструментов (коих не так уж и мало: vcpkg, conan, hunter, cppan, build2, buckaroo). Что из этого выживет и какие даст плоды — будем посмотреть, только время сможет дать ответ.

Но работа идет. И идет она для того, чтобы некий условный Вася Пупкин (особенно если он начинающий C++ программист) мог написать в своем проекте:
deps: A-1.2.3, B-2.3.4

а некий удобный в использовании инструмент ему это в проект подтянул со всеми зависимостями. Что уже будет в основе — git submodules, родные менеджеры зависимостей конкретных ОС, единый репозиторий на машине разработчика и т.д. — это уже вопрос реализации.

И каких-то принципиальных технических препятствий для достижения такого результата я лично не вижу. Тут, скорее, главное препятствование — это вопли о том, что все это нинужно и ниасуществимо :)
Евгений, я понимаю Вашу «боль», но не разделяю Вашего оптимизма в отношении создания менеджера зависимостей для языков с внешней открытой компоновкой (ASM, C, C++ и т.д.). Далее мнение «рядового траншейного программиста» без особых заслуг.
Мне кажется, что в общем виде эта задача нерешаема средствами упомянутых языков, просто потому, что компановка исполнимой программы является внешней службой, не имеющей прямого отношения к языку программирования. И C, и C++ работают с единственной единицей компиляции за раз для создания объектного файла. Оставляя вопрос создания целостного исполнимого бинарного образа компановщику, как части операционной системы.
Во всяком случае, создание единой системы управления бинарными и сборочными зависимостями для сборки «абстрактного» отдельно взятого приложения — нерешаемо в обозримой перспективе. Поскольку для этого надо, чтобы все приняли одно из частных решений: какой-то конкретный вариант «песочницы», «бандла» и т.д. Или же потребовать интеграции почти всех бинарников в единое дерево (пресловутый UNIX way). А поскольку каждый из нас Бетховен…
Для unix way существует много менеджеров пакетов, которые с практической точки зрения можно считать изоморфными, и все эти способы вполне работоспособны. В Windows и MacOS есть более-менее общепринятые способы создания «песочниц». В MacOS homebrew, например, предоставляет вполне работающее средство для создания согласованного дерева бинарных (в широком смысле) компонентов вместе с необходимыми зависимостями сборки. Новые языки вроде Go и Rust тяготеют к статической компоновке, при этом Go в данный момент пытается стандартизировать формирование согласованного дерева исходников для сборки, а в Rust понятие модуля (несущественно, сколь совершенное) существует на уровне языка (что и делает возможным существование Cargo).
Ну, а идею «модулей» для C++ без предварительной стандартизации ABI я полагаю химерой разума и причудой бальзаковского возраста. Моя точка зрения, конечно, «голос с белтА», но «высоколобые гуру языка C++» в очередной раз занялись своей высоколобой фигней для того, чтобы не думать о более трудных и насущных проблемах языка. О чем Страуструп периодически говорит, но кому интересно его мнение…
Если говорить о «всеобъемлющих» менеджерах зависимостей, которые могут решать проблемы бинарных модулей (если я правильно понял про «песочницы»), то я и сам не сильно оптимистичен в этом отношении. Поэтому мне лично не очень нравятся те менеджеры зависимостей, которые формируют репозиторий загруженных зависимостей на машине разработчика.

Имхо, тут нужно решать проблему по частям. Сперва разобраться с зависимостями, которые представимы в виде архивов исходников. Т.е. менеджеры, которые позволяют, грубо говоря, автоматически скачать по необходимости A--1.2.3.tar.bz2, B-2.3.4.tar.bz2 и все нужные им *.tar.bz2, распаковать это куда-то и сказать пользователю: все, все твои зависимости в твоем распоряжении, дальше сам.

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

Да, это не полноценное решение. Но, по нашему совсем скромному опыту использования собственного лисапеда, это сильно лучше, чем ничего.

PS. Модули C++ я предпочитаю в этом контексте вообще не обсуждать. Ибо стараюсь не бежать впереди паровоза. Когда завезут модули в C++, тогда и будем с этой проблемой разбираться. Все равно это произойдет не сегодня и не завтра.
Новые языки вроде Go и Rust тяготеют к статической компоновке, при этом Go в данный момент пытается стандартизировать формирование согласованного дерева исходников для сборки, а в Rust понятие модуля (несущественно, сколь совершенное) существует на уровне языка (что и делает возможным существование Cargo).

И это самое правильное решение, собирать каждую программу в свой бинарник. Попытки всё линковать динамически имеют слишком много проблем и крайне сомнительный профит.

Моя точка зрения, конечно, «голос с белтА», но «высоколобые гуру языка C++» в очередной раз занялись своей высоколобой фигней для того, чтобы не думать о более трудных и насущных проблемах языка.

Я выше приводил пример. Гуру пытаются пропихнуть модули, критикуя макросы. Указывая на макросы как проблему, но. Пытаются ли они дать людям альтернативу. Как реализовать без макросов условную компиляцию? Как реализовать кодогенерацию без макросов?

Вот и получается, что даже если есть какой-то новый проект, которому нужен функционал макросов(а таких много), который захочет на модули и захочет красиво. Что делать? Неясно.
НЛО прилетело и опубликовало эту надпись здесь
if constexpr для простых случаев

Это не условная компиляция даже близко.

использование разных .cpp-файлов в рамках билдсистемы в сложных.

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

Compile-time reflection, пропозалы есть, работа ведётся.

Судя по тому, что я смотрел — скудно. Очень скудно. Её уже пол десятка лет обещают. Но это хоть что-то.
НЛО прилетело и опубликовало эту надпись здесь
Опять же, сугубо в моём опыте, условная компиляция нужна только при написании платформозависимого кода, что и так выходит за рамки языка.

Не выходит. Ситуация «нужен разный функционал в зависимости от условий определённых на стадии компиляции» существует в рамках языка. Применяется везде и всюду, только в боле слабом виде. Просто пример — я хочу сконфигурировать либу, чтобы у меня не комплиировались километры лишнего кода. Сейчас я этого сделать не могу, если только макросами.

К тому же, С++ это такой язык, где много платформозависимого кода. Это только чисто формально он «кроссплатформенный».

Чего вам там не хватает?

Кодогенерации. Хочу не только читать, но и писать. Какие-нибудь хуки. Допустим — вызывать что-то вызове функции, при выходе из функции, вызывать что-то при определении какой-то класса. Много чего можно сделать с рефлексией, что улучшим мою жизнь.
НЛО прилетело и опубликовало эту надпись здесь
А как модули что-то изменят со временем инстанциации шаблонов? Убрать их за явной инстанциацией можно было и до жадной инстанциацией (кстати, она была воспринята как спасение), и сейчас через extern template, но есть нюанс, и не один. Пока эту нетривиальную работу за нас никто не сделает, header-only просто более простой путь для разработчика библиотек. Или у Вас в проектах стопицот самописных шаблонов используются стопицот разных спрособов?
Я подозреваю, что влияние модулей на время компиляции будет сопоставимо с прекомпилированными заголовками.
Вот время компоновки может сократиться очень существенно, это да. Но проблемы макросов и транзитивных зависимостей — Вам ведь знакома ситуация, когда надо использовать динамическую библиотеку, собранную с другой версией рантайма?
НЛО прилетело и опубликовало эту надпись здесь
Hunter делает нечто подобное, но пока что выходит не очень: сложно поддерживать, сложно интегрировать свои пакеты. Из-за этого пакетная база ограничена и временами существенно отстаёт от апстримов, а это для пакетного менеджера весьма существенный недостаток.
НЛО прилетело и опубликовало эту надпись здесь
весь hunter написан на cmake
Хорошо, а если я разрабатываю библиотеку, которая в свою очередь зависит от spdlog. Как теперь избежать того, что бы программа, которая зависит от моей библиотеки и от spdlog напрямую, не использовала две независимые копии этого spdlog?
В чём проблема? Если у вас не ho, то вам это волновать не должно. У вас своё, а у юзера своё. Если у вас ho, зависимости внешние и/или торчащие наружу кишки — это плохо.

Поэтому в ситуации с нормальной организации кода и библиотек — никого профита, кроме какой-то экономии трафика/мета не зафиксировано. И то, далеко не факт, что что-то будет вообще сэкономлено в сравнении со стоимостью ПМ.

НЛО прилетело и опубликовало эту надпись здесь
На каком основании?
НЛО прилетело и опубликовало эту надпись здесь
Не смогут. У меня нет никаких библиотек в том виде, в котором вы представляете их. У меня компилтай зависимости, а не рантайм.
НЛО прилетело и опубликовало эту надпись здесь
вы просто пишете find_package
Ах если бы find_package работал как надо, не нужны были бы пакетные менеджеры. Не всегда дистрибутив имеет рабочую версию нужной либы в нужной версии. А так приходится писать find_package а затем if not_found — использовать своё из thirdparty.
По сути, hunter — это попытка сделать find_package, который бы работал на всех дистрах/платформах.
НЛО прилетело и опубликовало эту надпись здесь
примерно всех? :) Нет и, наверное, не будет такого дистра, где есть все версии всех либ.
мало кто из проприетарных товарищей пакетируют софт под арч
Но такая возможность есть и некоторые мейнтейнеры портируют бинари из других дистров, что решает проблему.
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
страдания в питоне — почему я должен ставить толстый менеджер пакетов только что бы добраться до нескольких небольших библиотек?
Может это конкретно проблема Python-а и PIP-а. В Ruby на RubyGems народ не жаловался, в Rust-е на Cargo не жалуются, в Java с Maven-ом вроде как так же не жалуются.
зачем дробить текущий С++ библиотеки мелкие пакеты ради какого то менеджера пакетов?
О дроблении каких библиотек идет речь?

Хорошо бы раздробить Boost, поскольку он является не одной библиотекой, а конгломератом из более чем сотни разных библиотек.

Но вот кто хочет дробить ACE? Или POCO? Или Botan?
менеджер пакетов для С++ в моем понимании это некая доп утилита рядом с компилятором, которая позволит стягивать/устанавливать свои cpp/h файлы
так?

Не свои, а чужие. И желательно именно исходные файлы чужих библиотек, чтобы их можно было собирать под себя.
НЛО прилетело и опубликовало эту надпись здесь
поэтому лучше стянуть весь буст
Лучше вытянуть 120 библиотек, чем 20 библиотек? Wow. Тут крыть нечем.
я не вижу профита в менеджере который стягивает другие библиотеки, при том что другие библиотеки я могу стянуть и сам
Вы, видимо, очень трудолюбивый человек. Я бы предпочел, чтобы за меня это сделал какой-то удобный инструмент.
менеджер пакетов как некоторое облако в которое все существующие библиотеки С++ авторы должны будут переделать и залить?
Лучше иметь какой-то формат описания пакета и его зависимостей. А так же, возможно, централизованный репозиторий таких описаний. Выкладывать же тарболлы можно так, как удобно разработчикам библиотек. Инструмент должен поддерживать несколько способов получения тарболла (что не так уж и сложно, если ограничится поддержкой именно tar.{gz,bz2,xz}, zip, 7z, репозиториев git, hg и svn).
очень сомневаюсь что они это будут делать
Это сильно лучше, чем заниматься опакечиванием своих библиотек для текущего зоопарка (deb, rpm, pkg, homebrew, vcpkg, conan, hunter и пр.).
НЛО прилетело и опубликовало эту надпись здесь
Простите, вы наговорили уже слишком много, так что давайте кое что уточним. Вот это:
они уже есть в apt-get/pkg/vcpkg
Существование вот этих инструментов вам кажется оправданным?
НЛО прилетело и опубликовало эту надпись здесь
apt-get/pkg — оправданы
Пожалуй, нет. Поскольку очевидно, что за пределами отдельных Unix-ов для вас жизни нет.
НЛО прилетело и опубликовало эту надпись здесь
vcpkg не оправдан в ввиду сложности скачивания нужного пакета без vcpkg
Инструмент X не оправдан, поскольку он не предполагает работы без инструмента X? Странный взгляд на реальность.

Но меня интересует другое: если вы в принципе признаете целесообразность существования таких вещей, как apt-get, pkg, vckpg, conan и пр., то почему бы не сделать следующий шаг и не ответить на такой вопрос: «Зачем иметь весь этот зоопарк вместо одного штатного менеджера зависимостей?»
НЛО прилетело и опубликовало эту надпись здесь
штатный менеджер зависимостей будет где то в сторонке
«штатный» и «в сторонке» — это несовместимые понятия. Это как с CMake. Если библиотека собирается CMake, то можно, конечно, обойтись без CMake и написать скрипты для сборки этой библиотеки под свою систему сборки. Но это не штатный сценарий использования библиотеки.
НЛО прилетело и опубликовало эту надпись здесь
По сути что сказать хотели?
НЛО прилетело и опубликовало эту надпись здесь
Вот и вытягивайте, вам кто-то запрещает? Только вот интересно, почему ваше мнение должно быть руководством для меня? Типа, вот у 0xd34df00d нет проблем с тем, чтобы стянуть весь Boost, значит и я должен с этим смирится.

Теперь по сути. У нас есть двухлетний опыт использования своего велосипеда для кроссплатформенного управления зависимостями. Этот велосипед может поддерживать как тарболлы, так и брать версии из git/hg/svn (как head-ревизии, так и конкретные ревизии). И этот опыт показывает, что когда можно в зависимостях указать тарболл в 1Mb или даже в 5Mb, то он скачивается и разворачивается за считанные секунды. Если же нужно тянуть конкретную ревизию из git-а или hg, да еще из репозитория с длинной историей, когда выкачиваются десятки мегабайт, тогда все становится намного более грустно. Подтягивания зависимостей длится не 3-4 секунды для среднего проектика, а 30-40 секунд и более. Если нужно сделать пару-тройку клонов проекта для проверки каких-то версий (мы используем hg, там проще клонами, а не бранчами), то как-то грустно сидеть и ждать это время.

Так что если есть возможность скачать 10Mb зависимостей вместо 100Mb, то я предпочту скачать 10Mb. Насколько бы лично вы не видели проблем в скачивании 100Mb.
НЛО прилетело и опубликовало эту надпись здесь
Так вы буст из гита что ли берёте?
Буст мы вообще редко используем. Был эксперимент в том, чтобы брать его из git-а, раз уж его попытались разрезать на модули.

Кроме того, откуда прикажете брать Boost-1.67 под Ubuntu 16.04?

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

Велосипед такой, каким он и был задуман. Он собирает зависимости только в рабочий каталог конкретного проекта. Без каких-либо попыток создать что-то вроде общего репозитория на машине разработчика (как это делает conan, к примеру). Нам такой подход привычнее и удобнее. И мы никому его не навязываем.

так что обобщать проблемы вашего велосипеда на всё плюсосообщество как-то странно.
Хотелось бы узнать, где мы обобщаем. Пока что сухой остаток от дискуссии в том, что многим активным персонажам заточенный под C++ менеджер зависимостей просто не нужен, т.к. они довольствуются тем, что есть в конкретных дистрибутивах Linux-ов, а на весь остальной мир начхать. Как по мне, то это плохо.
НЛО прилетело и опубликовало эту надпись здесь
Не проблема, но иметь возможность не вытягивать лишнего не помешала бы. Но важнее, конечно, иметь возможность без сложностей подключить любые другие необходимые зависимости. Кстати даже сейчас очень сложно подключить буст к своей программе, если дистрибутив не предоставляет нужной (свежей) версии. Там начинаются такие свистопляски с использованием не тех версий разделяемых библиотек, что врагу не пожелаешь.
в одном случае у вас 20 библиотек, которые вы прикручиваете друг к другу сами, а в другом — 2-3 фреймворка, в которых покомпонентное взаимодействие идет из коробки. По сути, если фреймворк достаточно хорош под ваши задачи, почему бы им и не пользоваться?
НЛО прилетело и опубликовало эту надпись здесь
это монолит потому что каждая из конгломерата использует соседа
поэтому лучше стянуть весь буст
И это не проблема. Scikit-learn использует Scipy и numpy, куча всего в C++ зависит от Eigen, boost и т.д. Транзитивные зависимости — это не страшно. Уже то, что можно использовать numpy без scipy — плюс. Также и с boost, было бы неплохо иметь возможность использовать core без остального табора.
Либо пользуйтесь экосистемой Python, либо Вы сами по себе. Например, собирайте образ в одном дереве зависимостей и «стрипайте» его от всего лишнего перед установкой. Многие так делают и довольны…
НЛО прилетело и опубликовало эту надпись здесь
НЛО прилетело и опубликовало эту надпись здесь
А зачем столько много дистрибутивов?
ХЗ, вот расплодились отчего-то. Если я пишу программулину, которая может работать и под Linux, и под FreeBSD, и под Windows, то каким дистрибутивом Linux-а мне нужно ограничится?
НЛО прилетело и опубликовало эту надпись здесь
Если программулина опенсорсная, то тем, под который вы её сами адекватно поддерживать сможете.
Ну вот, например. Нужна 3-4 калекам во всем мире. Не вижу препятствий к тому, чтобы без проблем баловаться с ней под разными Linux-ами. И не вижу смысла прибивать ее гвоздями к одному какому-то.

За исключением того, что в Linux-ах разные менеджеры пакетов. И разные пакеты в родном менеджере доступны в разных версиях.

Что вы предлагаете делать в таком случае?
НЛО прилетело и опубликовало эту надпись здесь
Зашибись. Если кто-то захотел попользоватьвашу софтину под Arch-ем или еще где, то пусть он трахается с тем, как подтащить все нужные софтине зависимости в его Linux-е.

Вопросов больше не имею. Если C++ников с такими взглядами на управление зависимостями большинство, то проще свалить нахер в мир Rust-а и забыть все эту плюсовую помойку вместе с ее адептами как страшный сон.
НЛО прилетело и опубликовало эту надпись здесь
неудобно, что под Ubuntu нужно подключать зависимости через apt, на Arch-е через pacman, на FreeBSD через pkg, а под Windows через vcpkg
Если бы только неудобно, у них же вечно разный набор доступных пакетов/версий и вечно этого набора не хватает и требуется адаптировать сборку под каждый дистр что бы добиться совместимости с инфраструктурой дистра.
В идеале пакетный менеджер дистра должен интегрироваться с пакетным менеджером языка — не должно быть разницы между apt-get install python-numpy и pip install numpy
В идеале пакетный менеджер дистра должен интегрироваться с пакетным менеджером языка — не должно быть разницы между apt-get install python-numpy и pip install numpy


Спорно. У всех своё понимание стабильности. Представьте вы в доживающим свой срок релизе Дебиана обновите из pip пакеты…
Ну ок.
Ситауция% есть библиотека А, сорцы открыты, лежит, например, на гитхабе. В библиотеке есть баг, есть issue в трекере, ему уже пара лет, а разработчику не до этого. По-идее, мейнтейнеры могу добавить патч и в пакете будет библиотека без этого бага. Как с таким подходом быть?
ставить из репозитория мейнтейнеров через pip (по ссылке, к примеру).
apt-get install python-numpy
==>
pip install http://debian.com/stable/numpy-1.2.3-deb2.tar.gz
НЛО прилетело и опубликовало эту надпись здесь
Эта возможность теряется только в том случае, если я хочу сохранить «консервативность» системы. У меня всё ещё остаётся возможность установить свежую версию пакета на свой страх и риск, так же как это делается через ppa или pip сейчас.
В арче есть PKGBUILD который тоже по зависимостям и плану сборки генерит пакет, очень удобно. Ну только зависимости тоже должны быть пакетированы, что обычно не проблема. Преимущество языкового пакетного менеджера в том, что он может быть один на все системы и таким образом (почти) исчезает необходимость поддерживать пакеты для разных систем. Как в случае с pip.
НЛО прилетело и опубликовало эту надпись здесь
если будет pip-аналог, то стабильные репозитории тоже появятся, возможно платные. Отчасти эту проблему можно решить, если можно будет указывать точную версию каждой зависимости через версию или хеш-суму.
НЛО прилетело и опубликовало эту надпись здесь
Концепты выглядят очень похожими на обычный `static_assert`. В чем их преимущество-то?
в отличие от static_assert, нарушение которого просто остановит компиляцию, концептами можно перегружать методы:
template <typename T>
  requires Container<T>()
void foo(const T &c) { // реализация для контейнера

void foo(auto &&val) { // реализация для не-контейнера

Концепты больше как синтаксический сахар (плюс, ускорение компиляции) для SFINAE через enable_if
Мне кажется, что главное в концертах — внятные сообщения об ошибках при попытке инстанциирования. В соответствии с задуманным при создании шаблона.
Не аргумент, static_assert тоже позволяет писать кастомные сообщения об ошибке
Речь про другое. Сейчас можно получить простыню сообщений об ошибках, где-то в дебрях которых будет сказано, что не удается найти operator<() для типа T. А с концептами есть надежда получить одно единственное сообщение, где будет сказано, что T не удовлетворяет концепту Comparable.
Ничто не мешает это реализовать на static_assert
Мешает то, что static_assert — это необязательная штука. Если разработчик об этом подумал, то написал. Не подумал или подумал, но забыл, и не будет static_assert-а. Тогда как концепты достаточно задействовать в декларации функции/метода и далее соответствие концептам будет проверяться автоматически.
Работа над регулярками не может не радовать…