LINUX.ORG.RU

C++, который мы потеряли

 


1

5

https://habrahabr.ru/company/infopulse/blog/279927/
https://www.facebook.com/olegchir/posts/1093480147341658

tldr: модули, концепты, транзакционная память, унифицированный синтаксис вызова, дедуктивный вывод параметров шаблонов, сопрограммы, контракты, рефлекшен, constexpr if, расширения для работы с сетью - ничего этого НЕ будет в 17

★★★★☆

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

если ты считаешь, что «This is completely legal under the existing Java memory model» неверно, покажи место в JMM которому это поведение противоречит

ну... я считаю что — C++, который мы потеряли (комментарий) — вот это высказывание Legioner вполне верно:

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

заменить здесь «clang» на «OpenJDK»...

правда в отличии от «clang» — «OpenJDK» это практически синоним слову Ява (приведёные выше альтернативные Явазапускалки — это курам-на-смех :-))...

особенно в свете девятимеллиардного-судебного-разбирательства Oracle->GoogleAndroid — становится ясно что теперь оказывается является незаконным так-просто-взять-и-написать свою Явазапускалку без разрешения Оракла :-)

покажи место в JMM которому это поведение противоречит

предлагаешь мне в наборе бумажек искать фразу о том что Явазапускалке НЕдопускается менять алгоритм на совсем другой?

это как искать в инструкции от микроволновоки фразу о том — что туда запрещено класть кошек :-) ...

а включать микроволновку внутри работающей стиральной машины — можно? :-D

ды блин! есть готовая основная реализация Явы, так что к чему нам тут разводить странную теорию :-)

а зная как реализованы Микроволновки и Стиральные машины — ты уже понимаешь сам — о том можно ли их засовывать друг-в-друга :-)

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

Ссылку на CppCoreGuidelines давали выше, но она тоже довольно спорная.

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

Сейчас нагуглить не могу, но натыкался на гитхабе на либу для работы со звуком(не помню конкретно под что), так она была написана на плюсах, но использовала от них только шаблоны и что-то еще. А линковалось как сишная либа. То есть никак class и прочего.

Есть еще вот такая штука, и подобные ей: https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b

Я пару проектов в этом стиле пишу. То есть, это C++ код, со всеми плюшками C++, но stdc++ не используется и линкуется с musl(на крайний случай с libc). В итоге получаем очень маленькие, статические бинарники с тотальным контролем над происходящим внутри. Как следствие - макс. производительность. Но это не для продакшена.

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

Есть еще вот такая штука, и подобные ей: https://gist.github.com/bkaradzic/2e39896bc7d8c34e042b

Don't use exceptions.
Don't use RTTI.
Don't use stream (<iostream>, <stringstream>, etc.)...
Don't use metaprogramming excessively...

Любители подобных рекомендаций уже сделали для себя Rust. Да и то без аналогов исключений (под названием panic) обойтись не смогли.

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

Ага, только раст более наркоманский, чем C++.

  • Строгая иерархия директорий.
  • Сырой cargo.
  • Зачем-то создает отдельный рабочий поток при старте приложения, даже если потоки не используются. Видимо для try!
  • Пока что уступает C++ по скорости.
  • Про наследование и прочее молчу.
  • Слишком жирная стандартная библиотека, при отсутствии нормальной динамической линковки.

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

Имхо, заменить унылый stdc++, на растоподобный(читай QtCore), добавить unsafe и модули, сделать нормальный constexpr, const переменные по умолчанию и будет шикарный C++. Увы, увы.

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

В Си++ тоже неплохо получается с Result. А исключения в роли panic.

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

Странные претензии. Особенно насчет сырого cargo - в Си++ такого вообще нет, ни сырого, ни хорошо сваренного.

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

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

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

Страуструп прав по всем основным позициям на данный момент если оставаться в рамках обсуждения развития С++. Или я какой-то бред не слышал?

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

И не будет. Слишком много условий. Тут нужен полноценный пакетный менеджер.

Хотел пожаловаться на отсутствие возможности задания опций сборки каждой зависимости, но они вроде как добавили «features», не уверен только, что это именно оно.

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

И не будет. Слишком много условий.

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

eao197 ★★★★★
()

модули

ничего этого НЕ будет в 17

НЕЕЕЕЕЕЕЕЕТ!!!

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

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 1)

транзакционная память

В случае с C++ это был бы просто феерический треш, потому что C++ не умеет отслеживать побочные эффекты.

hateyoufeel ★★★★★
()

Bartosz Milewski ‏@BartoszMilewski 5 марта Seattle, WA

It looks like C++17 will be a big disappointment. Jacksonville committee could not agree on any major features. Oh, well — back to Haskell.

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

Ссылку на CppCoreGuidelines давали выше, но она тоже довольно спорная.

Что там спорного? Прописные истины одни. Или ты из тех, «кто даже стандартную библиотеку не используют»?

rupert ★★★★★
()

хабр такой хабр

C++ такой C++

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

Bartosz Milewski
Oh, well — back to Haskell.

Пусть катит. Но у меня такое чувство, что он ни в хаскеле ни в с++ особо не сечёт. Его писунки читал. Муть и бред.

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

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

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

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

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

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

Он не такой и двоякий. Много где действительно решают, что лучше сделать добавить рантайм-проверки для массивов, иногда делая их отключаемыми. В С++, как обычно, выбор дают на откуп программисту. На примере того же вектора: хотим проверок - используем метод `at`, не хотим - просто доступ по индексу.

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

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

нет, не с этого. никто не сказал «стандарт ISO»

Как скажешь. Но если я создам язык, выпишу неполную спеку и назову её «стандартом», то она им станет?

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

Его писунки читал. Муть и бред.

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

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

Любители подобных рекомендаций уже сделали для себя Rust.

Спорно. По крайней мере, относительно метапрограммирования, учитывая наличие макросов.

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

Не будут. Все, кто хотел свалить с плюсов, давно уже с них свалили.

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

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

когда я узнал, что концепты и ranges пролетят мимо стандарта, я выдохнул

Года через три придется вдохнуть обратно.

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

Строгая иерархия директорий.

Ну строгая и что? Интерфейс библиотеки может совсем не отражать внутреннее устройство - все инструменты для этого есть.

Сырой cargo.

И в чём сырость проявляется? Это не говоря о том, что надежды получить аналог для С++ мало. Именно аналог, а не «ещё одну самую правильную систему сборки».

Зачем-то создает отдельный рабочий поток при старте приложения, даже если потоки не используются. Видимо для try!

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

auto res = foo();
if (failed(red)) {
    return error;
}

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

Чего? Это в расте-то жирная библиотека? С их манией всё что можно (даже рандом) в сторонние библиотеки выносить?.. И что не так с динамической линковкой? Она есть.

растоподобный(читай QtCore)

Хм... подробнее можно?

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

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

И всем от этого только лучше.

В общем случае это так, но есть нюансы.

Написали clang и используйте везде.

Шланг самый слабый конпелятор из большой тройки и медленнее гцц(ну это с си, как с крестами - не знаю).

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

Не нравится — доработай, благо лицензия позволяет.

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

Шланг гонится как замена всему и вся только из-за того, что оно анальное владение эпла и иже с ним. В этом нет никакой логики - делать из него что-то большее чем libclang.

Точно так же как и любой не гпл-проект. Зачем пацанам и прочим капиталистам коммитить в шланг, чтобы его использовали в интеграцию в левые проприетарные системы разработки, которые бы конкурировали с ихними.

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

Они там есть только из-за проблем говнокодеров в маздайстудии с разбором проектов в идешках.

Зачем нужны модули? В чём смысл? Может лучше сделать в кресты нормальный компилтайм, чтобы буст и прочие куллстори не собирались по 100500 лет из-за всяких «я у мамки хацкелист» с рекурсиями в шаблонах с типами с названиями по 20кбайт? Хотя уже сотни лет никаких профитов от шаблонов нет, но мамкины хацкелисты не знают усталости и ваяют, ваяют тоннами это дерьмо.

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

Точно так же как и любой не гпл-проект. Зачем пацанам и прочим капиталистам коммитить в шланг, чтобы его использовали в интеграцию в левые проприетарные системы разработки, которые бы конкурировали с ихними.

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

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

что printf не проверяет при компиляции тип передаваемого ему значения для вывода

Проверяет - просто страутруп балабол. Только это проверяется на уровне конпелятора, а не на уровне языка. На уровне языка это реализовать в рантайме нельзя(хотя можно).

В крестах потому принтф"а и нету, что не осилили, как и везде.

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

Зачем нужны модули? В чём смысл?

http://clang.llvm.org/docs/Modules.html#problems-with-the-current-model

Проверяет - просто страутруп балабол. Только это проверяется на уровне конпелятора, а не на уровне языка.

внеси, пожалуйста, ссылку на пункт стандарта, где описаны тайпчеки для printf

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

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

Пацаны какие? Которые коммитят, либо которые хотят полутать халявку/полутать результат? Если вторые, то да.

Шланг как сливал gcc - так и сливает. Причём всё больше и больше и прогресса нет.

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

транзакционная память

В случае с C++ это был бы просто феерический треш, потому что C++ не умеет отслеживать побочные эффекты.

Вот тут более подробно: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4514.pdf

(это патч к 14 крестам, в т.ч. SO/IEC 14882:2014(E))

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

плюс держать в уме, что теперь у нас есть почва для аппаратной транзакционной памяти. Вначале она появилась в Haswell, но отключена из-за бага (инфа есть в википедии). На Skylake ее включают-выключают туда сюда :) (например, см здесь: SKL054 - TSX abort may result in unpredictable system behavior - no fix)Есть процы, где работает прямо сейчас: Haswell-EX, Broadwell-C. Наверное, скоро починят, и будет всем счастье.

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

http://clang.llvm.org/docs/Modules.html#problems-with-the-current-model

Не поможет.

Compile-time scalability

Бенчмарки в студию. Ну чтоб там с бустом.

Шаблоны вдруг перестанут инстанцироваться? в типы с именем по 20килобайт/20мегабайт? Каким образом? Все тормаза из-за хеадеронли-шаблонов - как это поправят модули?

Я так и не понял что есть модули - как можно сконпелировать шаблон? Никак. По твоей ссылки я не нашел объяснения устройства. Может ты мне объяснишь?

Fragility

Альтернатива условной компиляции в студию.

Conventional workarounds

Убогая брехня - man pragma once

Tool confusion

Какое-то вранье. Ни у кого никаких проблем с этим нет, но у пацанов есть.

внеси, пожалуйста, ссылку на пункт стандарта, где описаны тайпчеки для printf

Конпелятор к стандарту не имеет никакого отношения. И причём тут стандарт? К чему ты про него задвигать начал?

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

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

Оно итак их умеет отслеживать. И да - портянка никак не может что-то уметь.

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

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

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

Есть процы, где работает прямо сейчас: Haswell-EX, Broadwell-C. Наверное, скоро починят, и будет всем счастье.

На Xeon E7 v3 работает, только они стоят от $1.2k за чип.

На самом деле, с аппаратной транзакционной памятью будет ещё хуже чем с STM. Если ты внимательно почитаешь спеки TSX, заметишь, что многие инструкции процессора гарантированно вызывают отмену транзакции. Среди подобных инструкций есть, например, syscall. Добавь к этому тот факт, что некоторые функции в libc могут быть реализованы как через сискол так и без него (gettimeofday - каноничный пример), и получится, что использование транзакционной памяти в C/C++ превратится в непрекращающуюся стрельбу себе по ногам из пулемёта.

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

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

Зачем? Всё что не доступно - потенциально с побочным эффектом. В ситуации с полным доступом к телу - конпелятор это выводит итак. А учитывая популярность всяких хеадеронли - это не проблема.

Да и к тому же - в конпеляторах итак есть список функций с реализацией без побочных эффектов.

Среди подобных инструкций есть, например, syscall.

И что с того?

Добавь к этому тот факт, что некоторые функции в libc могут быть реализованы как через сискол так и без него (gettimeofday - каноничный пример)

Зачем её вызывать в synchronized-блоке? Её можно спокойно переместить выше, ибо если она используется - она thread-safe и за своими состоянием следит сама.

Точно так же, как и принтф.

что использование транзакционной памяти в C/C++ превратится в непрекращающуюся стрельбу себе по ногам из пулемёта.

Ни одной причины ты не назвал. Достаточно сноски что synchronized-блоки только для пользовательского кода, либо для кода с synchronized-safe.

Ничем не отличается от текущей ситуации - флагов в функциях thread-safe так же нет, но пацаны живут.

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

Это же C++, тут не может быть одного подхода.

PS: да, std не перевариваю.

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

Ну строгая и что?

В C++ я могу располагать сорцы как угодно, так как #include содержит указанный мной путь.

Пруфы про поток есть?

На версии 1.4, или где-то так, писал маленькую прогу. В профилере была возня с инициализацией pthread, который мне совершенно не нужен.

И что не так с динамической линковкой? Она есть.

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

Хм... подробнее можно?

Я к тому, что stdc++ дно днищенское, которое ничего не умеет, но порождает тонны писанины. В то время, как растовская std на уровне QtCore. Но хотелось бы, что бы она была более модульной из коробки (если я правильно понял, то бинарник у либы ровно один).

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

Он ещё не скатился?

Ну вот я пока не вижу в языке вещей, которые бы были прибиты к компилятору, и без которых нельзя было бы без особого сожаления обойтись. Да, в своё время поделие от майкрософта баловалось тем, что разрешало писать inline с другой стороны от типа результата функции, что стандарт не предусматривал, и при этом (если я ничего не путаю) поощряло именно такой стиль написания. В результате исходники Miranda IM, например, отказывалось компилироваться под gcc. (Понятно, что кроме inline, там были и другие проблемы, использование win32 api, например). Потом gcc тоже разрешил такое написание, попало ли это в стандарт - не помню. Но этим никто не обязывает пользоваться, и это, по большому счёту мелочь.

А вот модули - это такая вкусняшка, которой начнут пользоваться сразу, как только появится возможность. Это чревато фрагментацией языка. И если не стандартизовать сейчас, то в следующий раз комитету придётся просто выбирать одну из существующих реализаций. Во-первых, далеко не факт, что она будет лучше, во-вторых, представьте себе, что комитету через 5 лет придётся выбирать между реализациями от MS, gcc и clang (2 из 3, кажется, есть уже сейчас). Угадайте, чья реализация победит, и какую роль в этом будут играть технические соображения, а какую - лоббирование. А пользователям проигравших платформ придётся догонять.

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

А вот модули - это такая вкусняшка, которой начнут пользоваться сразу, как только появится возможность.

Уже в VC++2015 update 1 появились модули, а сейчас и update 2 недавно вышел. Никто не использует. В Clang есть другая реализация с версии 3.7. Тоже что-то никто не рвётся в бой.

rupert ★★★★★
()

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

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

Всё что не доступно - потенциально с побочным эффектом.

То есть libm.so, функции в которой чистые по определению, идёт лесом. Ок.

И что с того?

Зачем её вызывать в synchronized-блоке?

Зачем printf, который гарантировано вызовет отмену транзакции при использовании TSX, вызывают в synchronized-блоке в описании этого расширения? Ссылка на Pdf в комменте, на который я отвечал.

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

Ой, а оказывается, автор текста по ссылке написал почти то же, что и я:

Дело в том, что модули нынче существуют в виде старой (от 2012-го года) реализации в Clang и относительно новой реализации от Microsoft. Конечно же, они не совместимы между собой (кто бы сомневался), а комитет по стандартизации пока не может решить, кто ему милее. Отличаются реализации, окромя мелочей, принципиальной штукой — трактовкой понятия макроса внутри модуля. Принадлежит ли он модулю, или должен быть виден наружу?

Оба подхода имеют плюсы и минусы, поэтому решить, какой брать, пока не могут. Поэтому всё будет наихудшим из возможных способов: в С++17 не будет вообще ничего, а вот в следующем стандарте, попомните моё слово, наверняка опять подожмут хвост и с тезисом «нам нужна обратная совместимость» выберут худшее архитектурной решение (экспортировать макросы).

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

Тоже что-то никто не рвётся в бой.

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

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

Да если честно и в Clang и в VC++ модули говняно реализованы.

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

То есть libm.so, функции в которой чистые по определению, идёт лесом. Ок.

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

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

Зачем printf, который гарантировано вызовет отмену транзакции при использовании TSX

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

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

Ссылка на Pdf в комменте, на который я отвечал.

Ну пдфка то ещё дерьмо, конечно. Хорошо, что такой мусор в стандарт не прошел.

А так - я отвечал про то, что в целом этому(наличию stm/htm) ничего не мешает.

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

транзакционная память

В случае с C++ это был бы просто феерический треш, потому что C++ не умеет отслеживать побочные эффекты.

Показательно то, как хотели STM сделать для C#. В Микрософте собрали большую команду, напрягли кучу людей, но в итоге так и не смогли совладать с неявными побочными эффектами. Если не забыл деталей, то получался слишком большой оверхед из-за того, что компилятор C# в отличие от компилятора Haskell не мог дать определенных гарантий относительно чистоты функций. Вот и приходилось производить лишние операции, так на всякий случай. В общем, гора родила мышь. Проект STM для C# в результате прикрыли.

Поддержу тебя. C STM для Си++ случилась бы та же история ;)

dave ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.