LINUX.ORG.RU

C++ — туда и обратно, или зачем нужен Boost

 , , ,


2

5

Мой предыдущий тред в Development собрал самое большое число ответов аж с сентября, то есть за последние 9 месяцев, и это лишний раз подтверждает упадок этого форума. Полагаю, кто-то должен это изменить, и поэтому мы с тобой, ЛОР, поговорим сегодня про C++.

Начиная с C++26 вместо std::function вводится пачка новых классов: std::copyable_function, std::move_only_function (доступна с C++23) и std::function_ref. Что же не так с оригинальным std::function, ты можешь спросить? А вот что:

#include <functional>
#include <print>

struct call_me {
    int x = 0;
    void operator()() {
        std::print("x was {}\n", x++);
    }
};

int main() {
    const std::function<void()> f = call_me{};
    f();
}

Несмотря на то, что переменная f объявлена константной (люблю оксюмороны!), у неё есть внутреннее состояние и оно меняется при вызовах. Компилятор это без проблем хавает.

Так вот, ковыряясь в том, зачем и кто вообще смог так насрать себе в штаны сам, я наткнулся на статью ребят, которые подводят список подобных косяков комитета C++, когда фичи живут по 10 лет и объявляются устаревшими.

Небольшой список фич, которые были придуманы, оказались не нужны/бесполезны/вредны и выкинуты:

  • Известный vector<bool>, живущий издревле в STL и про который все говорят, что его надо избегать. Частично заменяется std::bitset.
  • std::auto_ptr. Бесполезен, ломает контейнеры, выкинут на помойку в C++17.
  • Указание исключений у функции в формате throw(X, Y). Так же выкинуто в C++17.
  • std::iterator объявили устаревшим в C++17, собираются удалить в C++26.
  • std::aligned_storage и std::aligned_union добавлены в C++11, объявлены устаревшими в C++23, скоро удалят.
  • Ключевое слово register удалено в C++17, хотя всё ещё доступно в Си.
  • std::get_temporary_buffer и std::raw_storage_iterator удалены в C++20.
  • Потрясающее по эпичности фиаско с интерфейсом для сборщиков мусора. std::declare_reachable сотоварищи были добавлены в C++11. Выяснилось, что сборщики мусора для C++ писать либо никто не умеет, либо никто не хочет, поэтому в C++23 это всё удалили и сделали вид, что ничего не было.
  • Абсолютное безумие вокруг концептов, модулей и поддержки сети. Предложения одобряли, вновь отклоняли, переделывали, и по итогу теми же модулями до сих пор никто не пользуется.
  • Сопрограммы (coroutines). В том виде, в котором они есть в C++, это просто ужас. Достаточно того, что корутины требуют выделения памяти из кучи во время работы, а значит вообще не подходят для случаях, когда требуется серьёзная производительность. Например, в любом коде, требующим работы в реальном времени и не позволяющем делать системные вызовы.

Просто лютый трешак, который никто подчищать пока не собирается:

  • std::regex – лютый тормоз, рекомендуется не использовать.
  • Мертворождённый std::simd, добавленный в C++26 и уже с ходу не нужный вообще никому, потому что код с std::simd в два-три раза тормознее чем со сторонними библиотеками, просто голыми интринсиками, и даже медленнее чем просто цикл for.
  • std::async. Дескруктор ждёт завершения асинка и поэтому может залочить весь код тебе. Наконец починили в C++26, но эта штука была сломана 15 лет.
  • Отвратительно спроектированный <iostream>. Его наконец можно выкинуть и использовать std::print, но не все про это знают.
  • Абсолютно тормозные контейнеры map, set, unordered_map. Вместо первого можно использовать flat_map из C++23. Контейнеры в стандартной библиотеке Rust (BTreeMap) и другие реализации B-Tree Map их обгоняют по производительности, но тем не менее в C++ выбирают убогий дефолт.

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

В общем, всё печально, ЛОР. Такие дела.



Последнее исправление: CrX (всего исправлений: 3)

После того, как в с++ добавли рефлексию с их потрясающим синтаксисом, это просто привет:

template <typename H, typename T> requires std::is_standard_layout_v<T>
void hash_append(H& algo, T const& t) {
  constexpr auto ctx = std::meta::access_context::unchecked();
  template for (constexpr auto mem : nonstatic_data_members_of(^^T, ctx)) {
      hash_append(algo, t.[:mem:]);
  }
}

А все кто говорит, что в rust плохой синтаксис, нужно посылать изучать синтаксис плюсов.

AoD314
()
Ответ на: комментарий от yorshka
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <ext/stdio_filebuf.h>

int main()
{
    __gnu_cxx::stdio_filebuf<char> filebuf(stdout, std::ios::out);
    std::ostream cpp_stream(&filebuf);
    cpp_stream << "Muh thread safety!" << std::endl;
    return 0;
}

Опять без сишки и шагу ступить не могут. Сишка — лучший язык out there.

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

Ага. Нет комитета – нет проблем.

Какая-то не просто детская, но младенческая наивность. Решения по развитию языка кем-то принимаются в любом случае, назови это Core Team, Leadership Council, Steering Council или Lang Team вместо комитета, не изменится вообще ничего.

anonymous
()

Есть ощущение, что автор только по поверхности зачерпнул. C++ имхо без библиотек вроде Qt или того же Boost - лютое неприкрытое позорище. Зачем-то придумывают фичи ради фич, потом эти же фичи выкидывают, потому что они УГ или никто их не юзает. Добавляют новые фичи и так по кругу и никаких тебе сокетов в стандартной библиотеке. И кто-то ещё из этих говнофич устроит карго-культ, будет им поклоняться.

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

Какая-то не просто детская, но младенческая наивность. Решения по развитию языка кем-то принимаются в любом случае, назови это Core Team, Leadership Council, Steering Council или Lang Team вместо комитета, не изменится вообще ничего.

Тем не менее, такая ситуация почему-то сложилась пока что только в C++. Подобным уровнем безумия мог бы ещё Common Lisp похвастаться – и там тоже комитет есть! – но, ко всеобщему счастью, он давно сдох. Возможно, это всё совпадение и просто место проклято.

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

P.S. Как это использовать на практике:

#include <iostream>
#include <fstream>
#include <thread>
#include <stdio.h>
#include <ext/stdio_filebuf.h>

static void worker(int my_num)
{
    __gnu_cxx::stdio_filebuf<char> filebuf(stdout, std::ios::out);
    std::ostream cpp_stream(&filebuf);
    for (int i = 0; i < 1'000'000; ++i) {
        cpp_stream << "Thread safety! #" << my_num << std::endl;
    }
}

int main()
{
    std::thread t1(worker, 1);
    std::thread t2(worker, 2);
    t1.join();
    t2.join();
    return 0;
}
[~]-[%] ./a.out | grep -vE '^Thread safety! #[12]$'
[~]-[%] 

Если переделать на std::cout, накладывания будут:

Thread safety! #Thread safety! #1
2Thread safety! #1

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

Именно так. Только в сишке нет темплейтов и умных указателей и ещё кое-каких вещей, чтобы не писать кучу воды, а так был бы лучший язык.

Почему в Qt всё как у людей?

#include <QCoreApplication>
#include <QTextStream>

int main(int argc, char *argv[])
{
    QCoreApplication app(argc, argv);

    QTextStream out(stdout);
    out << "Muh thread safety!" << Qt::endl;

    return 0;
}
Skullnet ★★★★★
()
Последнее исправление: Skullnet (всего исправлений: 2)
Ответ на: комментарий от anonymous

не изменится вообще ничего

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

anonymous
()

Абсолютно тормозные контейнеры map, set, unordered_map. Вместо первого можно использовать flat_map из C++23. Контейнеры в стандартной библиотеке Rust (BTreeMap) и другие реализации B-Tree Map их обгоняют по производительности, но тем не менее в C++ выбирают убогий дефолт.

А как можно сделать так чтобы HashMap aka unordered_map тормозил? flat_map же не hash-таблица.

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

__gnu_cxx

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

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

А как можно сделать так чтобы HashMap aka unordered_map тормозил? flat_map же не hash-таблица.

Например, в Abseil есть flat_hash_map, и оно куда быстрее. Вообще, по первой ссылке есть таблица с бенчем, глянь её.

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

Мне вот интересно, какой смысл писать _не_ на GNU C/GNU C++? Зачем нужна поддержка сборки под MSVC и прочими расово неполноценными?

Под винду можно собирать даже на линуксе с mingw. И тестировать в Wine. И даже писать на ассемблере с синтаксисом AT&T и линковать его в .exe.

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

А как можно сделать так чтобы HashMap aka unordered_map тормозил?

Всё можно, подходов к реализации хэшмапов вагон и маленькая тележка - отличаются хэш функциями, открытой адресацией vs. списками, всякими оптимизациями типа simd (смотрите гугловский доклад 20летней давности), условиями рехешинга, стойкостью к атакам (и как следствие, требованием к наличию rng), дополнительными свойствами как-то сохранение порядка вставки или невлияние рехэшинга на производительность и т.д.

Я правда сомневаюсь что стандарт накладывает дофига ограничений, так что вопрос это не столько к языку сколько к реализациям в libstdc++/libc++.

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

Ну как минимум clang/libc++ сейчас в большем почёте чем gnu. Но да, чому бы не писать переносимый код, а не вендорлочиться на костыли.

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

Мне вот интересно, какой смысл писать не на GNU C/GNU C++?

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

Под винду можно собирать даже на линуксе с mingw.

И там тоже есть clang. Причём нативно, прямо в Visual Studio галочкой ставится. Mingw не нужен.

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

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

А clang, по-твоему, не поддерживает GNU C/GNU C++? O_o Как же ядро шлангом собирают тогда?

И там тоже есть clang. Причём нативно, прямо в Visual Studio галочкой ставится. Mingw не нужен.

Где «там»? На винде? Да ну её в топку. У шланга нет своих заголовочных файлов, линковщика, stdlib, ассемблера, etc для кросс-компиляции под винду (ему требуются таковые от mingw). На линуксе им не соберёшь для винды.

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

А clang, по-твоему, не поддерживает GNU C/GNU C++? O_o

Как же ядро шлангом собирают тогда?

Ну, как тебе сказать… в ядре нет GNU C++. В ядре вообще никакого C++ нет.

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

Но есть GNU C, лол. А шланг поддерживает GNU C++ тоже (__restrict__ — расширение GNU C++):

void complement(const unsigned *__restrict__ src, unsigned *__restrict__ dst, int n)
{
    for (int i = 0; i < n; ++i) {
        dst[i] = ~src[i];
    }
}
$ clang++ -std=gnu++14 -Wall -Wextra -O3 -c foo.cpp

Same for __attribute__((…)), etc.

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

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

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

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

cobold ★★★★★
()

К vector<bool> что-то вообще не по делу придрались.

Вы хотите чтобы конструкция vector<T> именно при T=bool вдруг меняла реализацию или сваливалась с ошибкой - советом использовать bitset? Или что вы предлагаете?

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

Что значит «не столь существенны»? Эти проблемы выливаются в лишнее потраченное время при разработке кода и, потенциально, дополнительные дефекты. И то и другое – деньги.

Знаешь, почему веб-дрисня захватила мир? Потому что она дешёвая.

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

Т.е. он уже меняет реализацию при конкретном типе? Тогда они точно упоротые.

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

У меня складывается впечатление, что стандарт стал просто помойкой для сброса фич нескольких компаний типа Facebook.

Мелко берешь. Этой помойкой давно стал и linux и freebsd и даже intel.

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

В железячных компаниях типа Intel и Qualcomm инженеры пишут на C++ каждый день. Принимая во внимание, что железячники очень плохие программисты, C++ они таки используют и он им не кажется сложным. Вывод: если не пердолиться и не выделываться, плюсы это обычный простой язык программирования на котором можно писать сложные программы особо не напрягаясь и даже не будучи программистом.

Да и в целом вброс у тебя унылый получился. Херни какой-то натаскал, которую итак никто не использует и бегает тут «rust лучше, rust лучше, смотрите»…

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

Ты предлагаешь логи писать в отдельный поток из каждого треда? Или предлагаешь делать отдельный поток под логирование исключительно ради синхронизации, которая уже есть в системе, но C++ её ломает?

Ну нормальный логгер обычно и запускает отдельный поток для слива данных в stdout/файл/сокет. При этом остальные потоки просто помещают логируемые данные в concurrent queue, без блокировок.

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

Вы хотите чтобы конструкция vector<T> именно при T=bool вдруг меняла реализацию или сваливалась с ошибкой - советом использовать bitset? Или что вы предлагаете?

Как раз наоборот, хотим, чтобы vector<bool> не менял реализацию, ну или точнее реализовывал тот же интерфейс, что и vector<int> или вообще любой другой vector<T>. Сейчас слишком легко написать такую функции, которая работает для всех типов, кроме bool:

template <typename T> void foo(std::vector<T>& xs) { ... }

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

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

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

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

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

А про что-то другое встречал?

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

Ну вот сишников встречал. Там в принципе можно сказать, что язык простой.

Почитай мой предыдущий тред. Очень здоровая часть сишников на самом деле не знают Си. «Указатель – это просто число», ага.

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

потраченное время при разработке кода

Вам его не оплачивают или в чем ваша проблема?

веб-дрисня захватила мир

Один момент только - под капотом этой веб дрисни хром написанный на c++

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

потраченное время при разработке кода

Вам его не оплачивают или в чем ваша проблема?

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

веб-дрисня захватила мир

Один момент только - под капотом этой веб дрисни хром написанный на c++

Ичо? Хромог написан один раз, а веб-дрисню пишут на каждый чих. Это как утверждать, что Си рулит потому что лялекс на нём написан. Если бы плюсы были такими замечательными, вместо веб-дрисни мы бы пользовались нативным софтом на какой-нибудь Qt.

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

Проблема в том, что я в итоге получаю худшую и более дорогую версию программ

Ну так и мы с вами не совершенны как люди

Ичо?

И то что там где нужно используют специализированный инструмент, а где пофиг там скотч и палки

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

Почитай мой предыдущий тред. Очень здоровая часть сишников на самом деле не знают Си. «Указатель – это просто число», ага.

Да, многие ловятся на каком-нибудь UB типа «int a[5]; int p* = a; p+=10; p-=10;». Но сишники, хоршо знающие си, существуют и их не так уж мало.

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

Да, многие ловятся на каком-нибудь UB типа «int a[5]; int p* = a; p+=10; p-=10;». Но сишники, хоршо знающие си, существуют и их не так уж мало.

Ну да, не мало. Но судя по моему опыту собеседований, всё достаточно тухло.

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

судя по моему опыту собеседований

это в смысле ты ходил собеседоваться или к тебе ходили?

в любом случае - сочувствую.
им, не тебе.

olelookoe ★★★★
()

процесс разработки Rust

На нем уже успели напереписать сравнимое количество легаси кода? Чтобы пересравнивать сравнимое.

anonymous
()

Что тут скажешь. Все правда. Деды из комитета просто места свои берегут.

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

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

anonymous
()

Часть из перечисленного (например, std::vector, throw-спецификатор, std::aligned_storage) всего лишь является подтверждением тезиса про «не ошибается лишь тот, кто ничего не делает». Совершили ошибку, осознали, постарались исправить – что могли, выбросили. Что-то (std::vector) не удалось. Ну или пока смелости не набрались.

Что-то вообще неадекватное. std::auto_ptr работал так хорошо, как это было возможно в рамках C++98. Чтобы сделать лучше пришлось внедрять move-семантику в C++11 и (емнип) делать отдельные правила для возврата std::unique_ptr из функций. Сам же std::auto_ptr в С++98 закрывал ряд проблем. Например, до С++98 метод:

class object {
public:
  object * clone();
  ...
};

оставлял вопросы о том, кто и когда должен удалять значение по возвращенному указателю. std::auto_ptr закрывал этот вопрос полностью.

std::set и std::map обладают двумя важными свойствами:

  • не инвалидируют итераторы;
  • хранят содержимое в упорядоченном виде.

И при выполнении этих условий они вполне себе быстро работают. А если оба эти условия вам не нужны, то, вероятно, и set/map вам не нужен.

Какие-то претензии непонятны. Ну не устраивает кого-то скорость std::unordered_map или std::map. Ну и что? Обычные классы, практически такие же, как написанные вами самими, никакой уникальной магии там нет. Возьмите что-то другое, что устраивает больше. Никто не заставляет держать в проекте только классы из stdlib и ничего больше.

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

Между тем, можно было бы вспомнить другие вещи, которые иллюстрируют проблемы design by committe не хуже. Например, export templates, которые были задекларированы в C++98. И которые должны были снизить издержки при использовании шаблонов. Но осилить их смогли только ребята из EDG, а для других компиляторостроителей оказалось слишкамсложна. Поэтому export templates тихо выпилили из стандарта. Ну типа не было совсем.

Или, скажем, интерфейс аллокаторов. В котором аналога realloc-а нет в принципе.

eao197 ★★★★★
()

Люди работают, предлагают, ищут варианты.

А как по-другому то? Идеальных языков не бывает, даже естественные языки меняются.

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

Клоун прав, 99% сишников си не знают. Да и вообще, зачем «знать» ЯП? Или вообще, любой язык, даже человеческий, зачем его знать? На нем надо говорить, передавать информацию, а не знать. И ЯП не надо знать, на нем надо программы писать. Что подавляющее большинство людей и делает.

ant1
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария