Pull to refresh

Comments 422

Хочется думать, что рано или поздно у них руки дойдут и до модулей. Серьезно, я готов недополучить всех этих плюшек, да даже ranges и concepts, лишь бы сделали модули.
Модули уже почти готовы (по крайней мере дело дошло до wording — «патча» к существующему стандарту). Если не будет найдено фатальных недостатков, то есть все шансы увидеть модули в C++Next.
Да, но это еще минимум до 2020 ждать. Формально. Я конечно надеюсь что хотя бы Microsoft сделают их побыстрее (уже есть подвижки), но хочется везде и немедленно. И в связи с этим куча всяких вопрос: например, сможем ли мы выкинуть на помойку CРР/HPP файлы и просто иметь CPP и всё? Потому что это уже надоело, и самое главное что по стандарту много чего нельзя делать header only, например специализации шаблонов.

Еще конечно хочется полностью новый STL. Текущая стандартная библиотека мне видится тупиком. Взять хотя бы std::string — на CppNow, Sean Parent рассказывал что у них там 4 реализации строк в коде. А все почему? Потому что обычный API этой строки убогий, а выкинуть и сказать «мы накосячили, давайте заново» никто не готов.
Еще конечно хочется полностью новый STL

В Оулу решено было забронировать все namespace stdцифры для будущего использования стандартной библиотекой. Тоесть когда-нибудь и правда может появиться std2::. У людей в комитете уже сейчас есть идеи для новой версии стандартной библиотеки. Но вот появится она наврядли в ближайшие 10 лет.
да уж, 30 лет не могут сделать нормальные строчки — поиск, замена, lower/upper/locale
30 лет «ходим на костылях», а комитет грезит о дальнем космосе
запилить строки, синхронизацию, работу с файлами и сетью (+ асинки) — закроет 95% потребностей программистов
одну либку возмешь, она зависит от boost::asio, другая с необходимыми вещами, что нет в первой — от libevent… кто-то еще притянул ProtoBuf, а еще один решил, что для разных клиентов будет удобнее Thrift(с их сервисами и транспортами)… в итоге в приложении 3-4 либки работы с сетью (неплохо бы еще ZeroMQ с подписками и RabbitMQ для message-queue), 2-3 вида строк и 5-6 реализаций мьютексов и умных указателей… рукалицо/больпечаль

что касается новой STL из-за строк, то это ты погорячился: достаточно одобрить extension methods и впилить icu-либку, уже будет счастье:
string toLower( string_view sv ) {… }
auto str = string(«Hello WORLD!»).toLower();

offtopic: конечно в узкоспециализированных вещах С++ замены нет, но НЕ для «железного» уровня рассматриваю C++ как низкоуровневую(нативную, шуструю) реализацию некоторых вещей для более удобной/человеческой(созданной для людей) среды, что-то вроде С++ — это интринсики для C#/Java (еще бы их interop был гладкий… мечты)
Чёрт бы с поиском-заменой, сами напишем. Дайте поддержку UTF-8 строк! Именно строк как набора символов, а не байт. ЧТоб итерирование работало посимвольно и т. д.
Есть годные на мой взгляд предложения, но до них не дошли руки и в C++17 их не будет :(

Можно ссылки? Я волшебное слово знаю — ДАЙ! пожалуйста!

Поддержка кодировок из коробки — рука лицо, неужели так сложно сделать конвертацию разных кодировок из коробки, и да поддерживаю все что сказано вышел про сеть, строки, я бы ещё рефлекшен попросил( вполне устроили бы флаги компилятора) и аналог protobuff/Thrift, локализацию, стандартные либы типа zlib, libpng, libjpg из коробки, xml парсеры, математические типы, хотябы float3, matrix4x4, quaternion и операции с ними. Мультиметоды ещё хочу, пусть медленные ну да и черт со скоростью.
Берешь графический движок, в нем Vector3, берешь физически движок в нет Point3, берешь звуковой в нем float3, берешь либу с поиском пути в ней Float3 и сидишь пишешь бесконечные конвертации точек и матриц из одной либы в другую, со строками такая же бида.

Cargo. Просто Cargo. И все эти 3 либы будут использовать один набор типов из крейта 3d-geometry.


Упс, мы же про С++. Нет, не судьба.

> Берешь графический движок, в нем Vector3, берешь физически движок в нет Point3

Строго говоря, Vector и Point — это разные типы данных (даже если одинаковые структуры данных).
Я думаю он имеет в виду «шоб с русским работало, а все немцы и турки идут в жопу».

Но это мысли — интересно в какие слова они облекутся.
Та же Java умеет и так и так. Хочешь — итерируешься по символам (кодпоинты идут… далеко идут), хочешь — по кодпоинтам. В чём трабла сделать аналогично в c++?

PS просто не всегда нужно умляуты и прочие радости учитывать при обходе строки (например, если ищешь цифры — то они никакого значения не имеют).
PS просто не всегда нужно умляуты и прочие радости учитывать при обходе строки (например, если ищешь цифры — то они никакого значения не имеют).
Если ищешь цифры (парсишь XML или там JSON), то достаточно работать с байтами если у тебя UTF-8.
Цифры — лишь пример. Вопрос в том, что умляуты и прочие код-поинты, не учитывающиеся как символ для некоторого класса задач не имеют значения. Да и кодировка может быть не одно-четырёх-байтовая UTF-8, а двубайтовый UTF-16.

PS под возможной кодировкой я подразумеваю, что для хранения данных в типе строки кодировка (по уму) должна быть одна, но её можно выбирать из разных кодировок, в то же время я знаю две универсальные кодировки — UTF-8 и UTF-16.
Итерация по символам юникода с полноценной поддержкой большого числа правил ресурсозатратна как по скорости обработки, так и по памяти.

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

Я бы вообще не изобретал велосипед, а пользовался исключительно средствами операционной системы. В STL включил бы только врапперы для их вызова. Для основных задач обработки строк этого достаточно. Ну а что касается поддержки экзотических случаев — не стоит ими засорять стандартную библиотеку.
Микроконтроллер и С++ 17-года? Ну-ны.
Мне кажется, что все-таки в МК используют либо свой диалект Си, либо некое подмножество современного С++.
Но то что язык идет в тупик — это факт.
(С++ реально крутой, но каждая итерация нового стандарта делает его все монструознее и монструознее)
Проблема в том, что никто не будет писать компилятор именно для какого-то подмножества, да и кто его будет стандартизировать. Поэтому я согласен с DistortNeo в том что раздутая стандартная библиотека имеет минусы — на маленьких контроллерах используется тот же компилятор и тот же язык (разве что системные вызовы из libc и иже с ним по необходимости приходится самостоятельно делать), и C++ там тоже очень полезно использовать, но по мере роста библиотеки, во-первых, будет усложняться портирование, а во-вторых будут учащаться случаи, когда хочется использовать вполне скромный стандартный класс, а он за собой дёрнет iostream — бабах, плюс двести килобайт кода, а на контроллере всего сто двадцать восемь. Языку очень-очень нужны модули и что-то вроде пакетного менеджера, вроде того что у Rust — лучше сподвигнуть людей писать больше лёгких в использовании библиотек, чем засовывать в комплект ещё больше батареек.
Языку очень-очень нужны модули и что-то вроде пакетного менеджера, вроде того что у Rust — лучше сподвигнуть людей писать больше лёгких в использовании библиотек, чем засовывать в комплект ещё больше батареек.
«Батарейки в комплекте» — штука тоже хорошая, но тут у C++ тоже огромная засада: так как каждый тянет одеяло на себя, то в результате в стандарте — очень странная комбинация из вещей, которые мало кому нужны (но зато против которых никто не возражал) и полнейшее отсуствие вещей, которые всем нужны, но про которые каждый хочет чего-то своего.

Простейший пример: ни запустить подпроцесс, ни разобрать параметры, пришедшие в main (с выделеним обязательных/необязательных параметров, etc) средствами стандартной бибилиотки нельзя. Разработчикам систем для микроконтроллеров это, в общем-то и не нужно — но зато нужно всем остальным!
std::system запускает подпроцесс. А разбирать параметры, пришедшие в main, можно далеко не единственным способом (как минимум, синтаксис параметров в винде и линуксах разный). И пусть лучше этот парсинг остается в виде отдельных либ, типа boost::program_options
std::system запускает подпроцесс.
Лучше бы он его не запускал. Количество дыр в безопасности, которые образовались из-за того, что в стандарте есть только std::system — не счесть.

Но да, запускает, тут вы правы.

А разбирать параметры, пришедшие в main, можно далеко не единственным способом (как минимум, синтаксис параметров в винде и линуксах разный).
С одной стороны — вы правы: для создания переносимых программ какой-нибудь getopt не годится.

С другой — это значит что сотни тысяч программистов пишут сотни тысяч велосипедов при написании простейших утилит (потому что требование «использовать только стандартуную библиотеку» у заказчиков встречается частенько). Зачем? Ради чего вся эта бурная деятельность?
Представьте себя на месте члена комитета. Вам предлагают стандартизировать реализацию фичи, для которой отсутствуют даже общие соглашения о том, как она должна работать.
А вы представьте себя на месте пользователя, которому нужно что-то простенькое написать — и которого мало волнует наличие «общих соглашений» вокруг фичи.

Я прекрасно понимаю почему члены комитета не могут решить эту проблему — но это не меняет того факта, что конечный результат (огромный и очень сложный язык, который, тем не менее «из коробки» не умеет «элементарных вещей») — очень неприятен.
UFO just landed and posted this here
Требование как раз вполне разумное: код, который не тянет за собой внешних библиотек, легко интегруется куда угодно, код написанный поверх разных сторонних библиотек зачастую интегрировать — та ещё беда.

Никогда не пробовали объединять код, написанный даже не на основе разных библиотек, а на основе всего-навсего всем известного boot'а? Когда один компонент хочет версию 1.20, а другой 1.50… подружить их бывает ох как непросто.
UFO just landed and posted this here
UFO just landed and posted this here
Вопрос в том, что умляуты и прочие код-поинты, не учитывающиеся как символ для некоторого класса задач не имеют значения.
Вот я и прошу пример «класса задач». Пока всё, что я видел распадается на два класса: либо оно нормально работает с UTF-8 с побайтовой адресацией, либо адресация по кодпоинтам задачу не решает, а просто загоняет проблему вглубь. Как я написал выше: «шоб с русским работало, а все немцы и турки идут в жопу». Я, в общем, понимаю почему такой подход международный коммитет по стандартизации не очень хочет поддерживать.

PS под возможной кодировкой я подразумеваю, что для хранения данных в типе строки кодировка (по уму) должна быть одна, но её можно выбирать из разных кодировок, в то же время я знаю две универсальные кодировки — UTF-8 и UTF-16.
И опять-таки дихотомия неправильная. Есть два класса кодировок:
1. UTF-8 — кодировка с которой просто работать и расширять языки не нужно
2. Всё остальные кодировки — работать с которыми сложно и потому расширять язык тоже не нужно

UTF-16 относится ко второму классу. UCS-2 (из-за которой в некоторых языках и операционных системах и появилось угробище под названием UTF-16) — да, была проста и красива. Хотя платила за это наличием своих собственных недостатков. UTF-16, увы, имеет все недостатки UTF-8 (один кодпоинт и один элемент строки — разные вещи), но также унаследовала все недостатки USC-2 (например бывает UTF-16LE и UTF-16BE, а это значит что вам нужен BOM и вам нужно знать есть у вас BOM или нет и т.д. и т.п.)

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

Вообще-то, в UTF-8 тоже есть BOM...

Я так понимаю, он выступает в качестве сигнатуры кодировки. Ссылку не найду.


Но в том же C# любой текстовый файл, записанный в кодировке UTF-8 по умолчанию будет иметь BOM.

Просто BOM — по определению Byte Order Marker. В UTF-8 никакого byte order нет и быть не может, так как единица анализа в нём — один байт. Возможно, очередное гениальное решение Майкрософта?
Это размер код поинта, а единица анализа — один байт, и следуют он точно один за другим в одном порядке на любой архитектуре. Проще говоря, парсится UTF-8 побайтово, в отличие от того же UTF-16.
Именно так. Майкрософт решил его использовать как маркет UTF-8 файла. Но это уже самодеятельность — мало что что ещё можно придумать чтобы жизнь себе усложнить.
Вообще UTF-16 не двубайтовая. Не путайте её c UCS2.
Да, именно так. Чтоб была какая-нибудь функция length, которая возвращает количество code points, и какой-нибудь operator[], который возвращает собственно code point.
Как где-то писал Страустру: «кажется глупым добавлять в язык конструкцию, чуть ли не единственное назначение которой — порождение ошибок определённого класса».
Именно строк как набора символов, а не байт.
Можете привести хоть одну задачу, где это реально нужно?

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

P.S. Так, навскидку: не забываем что upcase("ß") == «SS», что upcase(«i») ==«I» у большинства народов, но турков upcase(«i») == "İ" и т.д. и т.п.
Это реально нужно в любой задаче, где нужно что угодно делать с не-ASCII текстом. Распарсить XML, например.
Зачем там кодпойнты? Чтобы найти '<', '>', '/', кавычки — про код-пойнты знать не надо, работы «как с ASCII» хватит, так как кусок кодпойнта принять за '<' невозможно. Чтобы понять, пробельный ли символ — тоже. Чтобы сравнить открывающий тег с закрывающим — тоже. Что я не учёл?
Например того, что существуют многобайтные кодировки.

Вообще-то тут обсуждались строки в UTF-8, а не в произвольной кодировке.

Вам для парсинга нужен доступ по произвольному смещению? Если не секрет, то зачем?
Это то с чего началась данная ветка: дайте, типа, нам посимвольный доступ в UTF-8 строку.

На вопрос «зачем» ответа так и не последовало, хотя, я на 99% уверен в своей версии: «нам с русским языком работать не удобно, а о немцах, турках и японцах мы думать не хотим — пусть идут куда им захочется… хотят на три буквы, хотят — на пять или десять».

Как вы понимаете такая мотивировка в международном комитете по стандартизации вряд ли получит движение.
Посимвольный произвольный доступ в UTF-8 идея довольно сложно реализуемая. Посимвольный последовательный доступ сделать относительно несложно. В задачах парсинга это как раз очень облегчает жизнь. Для реалистичной по скорости реализации произвольного доступа нужно либо использовать UTF-32, что бьет по памяти, либо UCS-2, но она не покрывает весь юникод.

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

И уже разработчик будет решать, что ему использовать.
Если бы всё было так просто. Проблема в том, что переход между «потоком байт» (ну, например, именем файла в Linux'е) и «текстом» (ну, например, сообщением «файл «...» имеет размер «...» байт») вовсе не так очевиден как хочется и кажется.

Нужны что-то более сложное — вот тебе полноценные строки, но за них придется платить памятью и скоростью.
А что будет если вы отнесёте что-то не в ту категорию? Программисты очень часто не задумывась, относят что-то не в ту категорию — и если у вас есть два жёстко разделённых мира, то исправление этой ошибки — очень дорого. Если у вас и то и другое — строки (подход C++, Go, Python2 и множества других языков) — то жить становится гораздо легче.

Стандартизация библиотеки для работы с текстом — дело хорошее, только, ради бога, не засовывайте это прямо в язык.
Это то с чего началась данная ветка: дайте, типа, нам посимвольный доступ в UTF-8 строку. На вопрос «зачем» ответа так и не последовало, хотя, я на 99% уверен в своей версии: «нам с русским языком работать не удобно, а о немцах, турках и японцах мы думать не хотим — пусть идут куда им захочется… хотят на три буквы, хотят — на пять или десять».

А японцы, которых Вы упомянули, по-Вашему, что UTF-8 — не используют?!
Это необходимо всем у кого алфавит не на латинице, то есть как минимум 3 миллиардам человек = китайцы + индийцы + японцы + корейцы + таиландцы + пакистанцы + бангладешцы + арабы + и так далее… То есть даже без России — это половина человечества, если не больше, так как в Африке существуют алфавиты тоже основанные не на латинице.
Человек убежден в том, что 99% страждущих посимвольный доступ к UTF-8 строкам хотят весьма кривую реализацию, которая будет отлично работать с кириллицей и не работать с иероглифами, немецким и турецким языками и т.п. Ибо эти 99% человек просто не сталкивались с этими проблемами, а потому не представляют, во что превратится нормальная поддержка UTF-8 в стандарте. И я с ним согласен, впихнуть UTF-8 в стандарт — это надо постараться. Да и кому оно ДЕЙСТВИТЕЛЬНО надо?
Я последние 3 года разрабатываю старый Web-проект с бэкендом на плюсах (+ свой проект тоже на плюсах). Ни разу не было реальной необходимости в посимвольном доступе к UTF-8 строкам.
В тех же случаях, когда сложная работа с UTF-8 действительно нужна, лучше просто взять специальную библиотеку, а не желать этого в стандарте языка.
Это примерно как желать 3D движок в стандарте C++. Но что-то я не вижу желающих интегрировать в стандарт, например, OGRE.
Стоп. Давайте разделять UTF-8 и Unicode.

UTF-8 — это просто способ кодирования 31-битных значений в виде последовательности 8-битных байт. Он никак не привязан к смысловому содержанию этих значений.

Для подавляющего большинства практических задач обработки строк посимвольный доступ (=преобразование UTF8 в UCS2/UCS4 на лету) не нужен — можно работать напрямую с UTF8 представлением строки.

Если всё-таки нужен произвольный посимвольный доступ, то будет гораздо эффективнее преобразовать строку в массив 2-байтных или 4-байтных значений, а после работы преобразовать обратно. А если ещё хочется и менять значения символов на месте, то как вы себе это представляете для UTF8?
Ну, работа с текстом требуется куда чаще, чем работа с 3D. Давно уже большая часть приложений не сводится к «продвинутому фортрану».
Да, вы правы, если в строке интересны только ASCII символы — можно обойтись без понимая UTF-8 и Юникода вообще.
Но вот мне, например, недавно нужно было искать в тексте кавычки не только обычные, но и “/”, «/», а также символ троеточия.
Символ троеточия ищется в UTF-8 как последовательность трёх байт 0xe2 0x80 0xa6 — для этого совершенно не нужны глубины глубин.

Только сначала прогоните текст один раз через фильтр, убедитесь что это корректный UTF-8…
UFO just landed and posted this here
Если вы пишете текстовый редактор, вам скорее всего потребуется разбивать текст на слова, причём разделителями, как вы понимаете, могут служить не только ASCII-пробелы.
А ещё их может не быть — совсем. Как в Китайском и Японском, к примеру. И вам всё равно нужно знать на каком языке текст и нужна отдельная процедура, которая этим занимается.

Или если вы пишете компилятор для языка программирования, поддерживающего юникодные спецсимволы (ну как в Mathematica и Haskell), то вам тоже понадобится посимвольный разбор.
Зачем? Если вам достаточно «халтурной» реализации — посимвольной обработки хватит. А если вы хотите полноценную поддержку, то тут всё сложнее. Нужно как-то обрабатывать LTR, возможно придётся как-то озаботиться сравнением Hangul Syllables и Hangul Jamo и прочее.
UFO just landed and posted this here
Не понял, чего нет в китайском и японском? Пробелов?
Угу. Для того, чтобы понять где можно переносить строку нужно использовать достаточно сложный алгоритм, содержащий, среди прочего, ещё и словарь иероглифов…

Ну в этой-то отдельной процедуре настоящие юникодные строки вам будут нужны, так ведь?
Скорее нет, чем да. Оперировать с отдельными символами вам там нужно будет очень редко, вполне достаточно требования что на входе — корректная UTF-8 строка. Вот это — да, нужно чётко отделять уровни где у вас std::string — это ещё «поток байт» и уровни где это уже текст (==корректный UTF-8).

Со строками например такая проблема: у строки есть и size() и length(). Вот представьте вы начинающий разработчик, хотите понять что это за функции такие? Интуиция как бы подсказывает, что length = количество буков (символов), а size = размер "сколько вешать в байтах". Но не тут-то было. К тому же, в упор непонятно, почему это length() — функция, а не свойство строки. Но это уже другая история.


Про UTF-8 я вообще помалчиваю. Мне бы хоть ASCII но с вменяемым синтаксисом. Где split(), to_lower(), и прочие очевидные вещи? Почему я использую Boost на каждый чих? Ведь Boost — это глобальные функции, а это полная отсутствие discoverability, то есть, есть у вас IDE, нет ее, не важно, т.к. комплишн по всем глобальным символам еще-не-заимпортированных заголовков не сделать в принципе.


Экстеншн-функции — хорошая, проверенная в C# тема, но с ней тоже как-то не торопятся. А даже если сделают, мы что, будем стандартизировать эти "патчи" стандартным типам? Или каждый тихо в гараже запилит свой split() и его будет шипить как сорцы?


Вообщем, проблем много.

UFO just landed and posted this here

"Стандартный" split должен быть эффективен и широко применим. Есть n3593 с довольно адекватной мотивацией. Ждёт как раз упоминаемых string_view и Ranges.

Народ просто, похоже, не понимает, что большинство этих «ненужных» фич принимается именно для того, чтобы была возможность нормально имплементировать широко используемые фичи в стандартной библиотеке. Например, нормальные умные указатели были невозможно без мув-семантики, туплы — без вариадик темплейтов. Отсутствие же вариадик темплейтов не позволило имплементировать аналог printf-а, что привело к возникновению стримов — единственного возможного решения для типизированного ввода-вывода в таких условиях.
Понимают, но оптимизация в прикладном коде, к сожалению, не возникнет сама собой и везде. Выходит для того, чтобы пользовательский класс стал «эффективным» в рамках STL, народу также нужно разбираться во всех тонкостях и особенностях реализации стандартной библиотеки, а это, учитывая размер разбухающего стандарта, уже слишком, на мой взгляд…
30 лет не могут сделать нормальные строчки — поиск, замена, lower/upper/locale
30 лет «ходим на костылях», а комитет грезит о дальнем космосе
запилить строки, синхронизацию, работу с файлами и сетью (+ асинки) — закроет 95% потребностей программистов

Точно вместо удовлетворения необходимостей, комитет занимается тем что блаженно чешет своё ЧСВ. :(

PS создайте кто-нибудь петицию на Change.org чтобы до этих зажравшихся козлов в комитете наконец дошло!
Модули — это основная причина, делающая крайне затруднительным использование стороннего кода и невозможным — менеджеров пакетов. Кстати, экспериментальная реализация модулей уже есть в Visual Studio 2015 Update 2. Но она настолько сырая, что пользоваться ею не хочется совсем.

STL ужасен до невозможности после опыта работы с более новыми языками с нормальными библиотеками. Больше всего бесит широкое использование беззнаковых типов и смешение знаковых/беззнаковых. Затем — ужасный iostream с нелогичными перегрузками и форматированием. В качестве прикола пытался написать аналог .NET String на C++ с SubString (с указателями), особенно String.Format с variadic templates. Даже работало и было на порядок удобнее printf и тем более cout.
Хм, имелось в виду «отсутствие модулей» — плохо.
И я очень надеюсь, что с введением модулей будет полностью переработана STL.

Я вот думаю, так под шумок модулей можно и STL переписать. Но это скорее мечты.

Основная проблема в том, что одним из столпов С++ является обратная совместимость: если кто-то 10 лет назад использовал какую-либо функцию, то её уже не удалить из стандарта. А превращать язык в снежный ком никто не хочет.
Есть же примеры такие как auto_ptr и не COW-строк в последних stdlibc++

auto_ptr до сих пор поддерживается, а не COW-строки в GCC начали разрабатываться за много лет до появления стандарта (оказалось что COW-строки на многопроцессорных системах сильно медленнее, а экономия памяти редко когда стреляет).


Если вы не обнаружилось что из распространённых компиляторов только один использует COW-строки, да и тот планирует «при удобном случае» от них отказаться — фиг бы чего вышло. Да и то: это изменение старые программы не поломало, максимум — изменило потребление памяти.
И когда-то auto_ptr из стандарта совсем уберут, как убирают std::binary_function из c++17, то есть при указании -std=c++17 он не будет определён.

Реализацию, наверное, не template-функций убрать из библотеки будет сложно, но никто в приципе не мешает старым программам требовать старую stdlib.

А насчёт COW — это я имел ввиду то, что бинарную совместимость тоже иногда ломают.
А насчёт COW — это я имел ввиду то, что бинарную совместимость тоже иногда ломают.
А тут как раз очень забавно. У Microsoft'а она вообще ломается каждую версию, а в Linux'е введение не-COW строк, строго говоря, бинарную совместимость не сломало. Тeперь в стандартной библиотеке есть std::string и std::__cxx11:string — и, в теории, ничто не мешает библиотекам и программам продолжать поддерживать и использовать оба вида строк…
Ну нет, всё-таки одновременно два типа строк смешивать не получится нормлаьно, там же сигнатуры разные. Только если через c-интерфейс.

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

А сейчас нет чего-нибудь что требует страый gcc для сборки?
А сейчас нет чего-нибудь что требует страый gcc для сборки?
Старые программы испольщующие, скажем, iostream.h? Это, кажется, самое заметное несовместимое изменение…

Предыдущие «циклы» (переход с GCC 2.95 на GCC 3 и с GCC 3 на GCC 3.4+), кажется все уже и забыли…
> а в Linux'е введение не-COW строк, строго говоря, бинарную совместимость не сломало.
Строго говоря как раз таки сломало.
Если разные модули будут использовать в своих API stl строки, и будут собраны в режиме С++11, но один компилятором GCC-4.*, а второй — GCC-5 и выше, то они будут ABI не совместимы.
Если разные модули будут использовать в своих API stl строки, и будут собраны в режиме С++11, но один компилятором GCC-4.*, а второй — GCC-5 и выше, то они будут ABI не совместимы.
Зависит от того — как именно вы используете GCC-5. Вы можете им собрать свою библиотеку с std::string, с std::__cxx11:string и даже с обоими вариантами одновременно.
> Зависит от того — как именно вы используете GCC-5
В общем случае нет, не зависит.
Собрать то свою библиотеку я действительно могу как угодно, но если какая-либо библиотека уже собрана (например, компонент без исходников) пусть в gcc-4.9, а в дистрибутиве линукса установлен gcc-5+ (с новым ABI по умолчанию), то эта библиотека будет не совместима с поставляемыми в дистрибутиве другими библиотеками (они то используют std::__cxx11:string вместо std::string).

По Вашей ссылке об этой проблеме тоже написано:
> If the third-party library cannot be rebuilt with the new ABI then you will need to recompile your code with the old ABI.
А «your code» вполне может быть и энное количество поставляемых в системе библиотек.
Какая же это совместимость ABI, если требуется «recompile your code with the old ABI»?

В Clang модули реализованы уже несколько лет (правда не совсем тот вариант что пошёл в стандарт).

Рад слышать! Тоже очень жду модулей!
А где можно почитать «почти готовый» стандарт про них? Интересно, как он выглядит на данный момент.
Мне все интересно! Пишите больше, это очень интересная тема.
Некоторые мысли по статье
1. Как «if (init; condition)» будет взаимодействовать с объявлением переменных внутри круглых скобок if, т.е. «if(int x = foo())»?
Кстати, сама по себе форма уже очень близка вот к этому https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html, т.е. к тому чтобы сделать стейтменты выражениями, как в Scala или Nemerle.
2. Structured bindings… получается очень забавно — в С++ со всех сторон подошли к прямой реализации кортежей средствами языка, но видимо из-за «legacy» синтаксических особенностей так и не сделают. А так почти все есть — и списки инициализации, и pair/tuple, и вот теперь structured bindings…
1. Как «if (init; condition)» будет взаимодействовать с объявлением переменных внутри круглых скобок if, т.е. «if(int x = foo())»?

Если нет `;` в `if`, то считается что в круглых скобках condition. Другими словами — работать будет так же, как сейчас.

2. Structured bindings… получается очень забавно — в С++ со всех сторон подошли к прямой реализации кортежей средствами языка, но видимо из-за «legacy» синтаксических особенностей так и не сделают. А так почти все есть — и списки инициализации, и pair/tuple, и вот теперь structured bindings…

Одно из предложений, которые обсуждали на собрании, как раз было что-то похожее на «кортежы средствами языка». Но это был скорее исследовательский доклад, и решено было пока продолжить исследования и посмотреть что получится.
А если я там напишу более двух стейтментов? if( foo(); bar(); baz(); condition )
Интересны пределы возможностей, так как реально это очень похоже на возможность использования цепочки стейтментов в выражении.
Кстати, «if constexpr» это небось из D «static if» таки протащили?
Ну не удивительно, т.к. Александреску позиционировал static if как основное преимущество D.
static if кроме как для шаблонов где-то нужен?

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

Компилятор выкинет тождественные if'ы даже если они не помечены как constexpr. Суть в том, чтобы подавленная ветка даже не компилировалась.
Тем самым возможно иметь два различных объявления внутри if стэйтмента:
if (int x = foo();  double y = bar());

А также вместо инит стэймента может быть экспрешн стэйтмент:
if (do_something(); int x = foo());

Кстати, кланг уже поддерживает эту фичу (спасибо мне и Ричарду Смиту :)
А expression-statement — это для lock-guards, или для чего-то ещё?
Видимо в бусте закончились фичи которые можно спереть в стандарт.
Фичей ещё очень много :)
Просто комитет не занят стандартизацией только библиотек Boost.
Непонятно чем он вообще занят. Импортов нет, концептов нет, filesystem нет. Даже pragma once(или ее аналог) не могут в язык внести.
Даже pragma once(или ее аналог) не могут в язык внести.

Может, потому что эту «фичу» невозможно корректно имплементировать? Уже сто раз оговорено, что pragma once не должна использоваться в нормальном коде.

Можно ещё раз для тех, кто всё пропустил? Хотя бы ссылку. Потому что у нас pragma once используется и не вызывает никаких проблем, а кодовая база собирается разными компиляторами.

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

У систем сборки (того же make, к примеру) есть точно такая же проблема — они не могут различать артефакты (цели) по символическим ссылкам в общем случае.


Означает ли это, что системы сборки на основе артефактов не следует использовать? Нет, не означает. Это означает что всевозможные ссылки надо использовать осторожно.


И с pragma once то же самое.

И с pragma once то же самое.
Нет, не то же самое. Систем сборки не страдающих от указанных вами проблем я не видел (для языков без модулей, в общем-то, и альтернатив не придумать), а для pragma once альтернатива есть, описана в стандарте и работает ничуть не хуже.
Систем сборки не страдающих от указанных вами проблем я не видел

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

Хм, вроде как SCons по умолчанию использует md5 по содержимому файла для определения его уникальности.
Если бы SCons этим занимался, то он бы обрабатывал мало-мальски сложные проекты невменяемо долго. MD5 Scons использует, но уже после проверок на изменение даты. Если файл изменится, а дата модификации и размер останутся неизменными — SCons ничего не заметит…

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

Это очень похоже на мое о нем впечатление)


Смотрю в доках:


By default, SCons keeps track of whether a file has changed based on an MD5 checksum of the file's contents, not the file's modification time.

И судя по тем же докам, проверка времени изменения перед проверкой хешей опциональна и требует явного включения — Decider('MD5-timestamp').

Спасибо.


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

GCC первоначально выдавал предупреждение об отключении pragma once, если компилируемый код использовал её. Тем не менее, в релизе 3.4 GCC код обработки команды pragma once был исправлен для корректной работы с символьными и жёсткими ссылками. Данная возможность была сочтена полезной и предупреждение было убрано
https://ru.wikipedia.org/wiki/Pragma_once

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

Она не то чтобы очень проблемная, в большинстве случаев она работает так как надо. Вот только вносить в стандарт то что «в большинстве случаев работает так как надо» — плохое решение. К тому же сама возможность полностью корректной имплементации под вопросом, и при этом есть решение, лишённое недостатков pragma once. Поэтому отсутствие её в стандарте — закономерно и правильно, как по мне.

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

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

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


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

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

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

При использовании одномённых гардов компилятор ошибку, конечно, выдаст — но найти ее причину будет не проще чем найти #define true false. Потому что компилятор попросту не включит один из двух конфликтующих заголовочный файлов — и потом выдаст кучу воплей о необъявленных типах и функциях.

UFO just landed and posted this here
Почему бы тогда не позволить #pragma once(MY_HEADER), которая была бы «сахаром» для

#ifndef MY_HEADER_#FILEHASH#
#define MY_HEADER_#FILEHASH#

#endif?
Потому что это решение — хуже существующего. Например потому что существующее решение не зависит от хеша файла.

P.S. Когда может оказаться полезным трактовать разные файлы как одинаковые? Когда это — разные версии одного и того же файла.

P.P.S. Я не говорю что существующее решение — идеально. Но так как все «простые решения» имеют свои подводные камни, то лучше не пытаться забить очередной костыль (который всего лишь заменит одну проблему другой), а всё-таки подумать на тему модулей. Ну не создают нормальные люди новые файлы так часто, чтобы эти три строчки были проблемой, не создают!
Генерите уникальный GUID на каждый новый файл. Всё, проблемы больше нет.

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

inline для переменных — если в разных единицах трансляции присутствует переменная с внешней линковкой с одним и тем же именем, то оставить и использовать только одну переменную (без inline будет ошибка линковки);


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

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

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

Чтобы так «пальнуться» надо написать что-то типа inline int a = ...; в двух .cpp вне классов/методов/неймспейсов. Нечаянно взломать сейф, так сказать

Не-а. Надо как раз забыть у статик-переменной дописать static, который сделает ей локальную видимость.

std::string_view

std::array_view я так понимаю не будет?

В C++17 не будет, но есть надежда что скоро появится в std::experimental::

Тут кстати интересная дуальность. Везде в STL у нас обобщенные алгоритмы которые берут begin()/end() не важно откуда. А для строк почему-то свой string_view хотя по логике вещей могли бы дать и array_view и сказать "а дальше вы сами". Ведь по сути, пока нет поддержки юникода, строки и массивы — это одно и то же :)

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


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

Ну, если на то пошло, давайте признаемся что в современном мире более рационально сделать некий интерфейс IEnumerable<T> (привет C#) и поддержать ключевое слово yield, которое дает возможность произвольно возвращать коллекцию даже тогда, когда это дерево и нужна рекурсия. В С++ сейчас писать итератор для дерева в рекурсивном стиле невозможно.


А потом можно передавать не begin()/end() а просто сам объект. И все счастливы.

Примерно так и есть. Сделано, кстати, в одном языке на R, 4 буквы в названии. Ооочень удобно, даже без yield — когда итерирование по коллекции — 1 метод, а не как минимум 3-4.

Что за язык? Ravascript? Rwift? Rython? Не томите!

Rust вообще-то. Почитайте на досуге, если интресно. Там, в частности, исправлены многие косяки С++.

А можно от несогласных пояснение, где я не прав? Или в споре о С++ другие языки и, в частности, потенциальных конкурентов, упоминать запрещено?

Ну… евангелизм бывает навязчивым. (:


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

Потерпите пару годков. Go тоже несколько лет назад усиленно PRили. Потом успоколились. Сейчас вот Swift и Rust.

P.S. Swift меня не волнует от слова никак — точно так же, как не волнует, скажем, язык 1С (зачем мне язык намертво завязанный на чужую экосистему?), а на Rust — я поглядываю, но пока не решился ничего серьёзного на нём писать.

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

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

есть функция std::distance, который как раз выдаст длину контейнера, определяемого итераторами begin и end. Точно так же у большинства контейнеров определен конструктор, принимающий итераторы и возвращающий, по факту, подмассив указанного размера: std::wstring ws = L«sometext»; std::string s(ws.begin()+4, ws.end()); вернет «text»
Проблема в том, что в общем случае очень трудно определить, какая категория итераторов пришла. Да просто нет возможности поставить ограничение «здесь принимается random access iterator».
Плюс, ограничение на тип элемента делается криво.
Плюс, функции, принимающие итератор, обязаны быть шаблонными — а принимающие срез конкретного типа — нет.

В общем, пользоваться можно — но срезы удобней.
Почему же трудно то?
template std::enable_if_t<std::is_same<std::random_access_iterator_tag, typename T::iterator_category>::value,void>
doSomething(T begin, T end) { /*...*/ }
Вот вам и ограничение «здесь принимается random access iterator».

Шаблонность в общем случае тоже необязательно — можно пользоваться auto функциями/лямбдами

Сравните с


void doSomething(stdext::slice<int> someslice) { ... }

  1. Нет enable_if_t. Который в большинстве случаев применяется как костыль в отсутствии концептов
  2. Нет шаблонности — можно имплементацию прятать в другой модуль.
  3. Банально легче читать
я доказывал только реализуемость

Так я тоже писал, что возможно — но неудобно.

std::variant

Они таки вставили null state. Не очень хорошо, честно говоря. Я так понимаю, это жертва для обеспечения exception safety. Хотя могли бы потребовать noexcept для деструкторов и move конструкторов.

Они таки вставили null state.

Да, он называется valueless_by_exception() и возникает крайне редко.

Хотя могли бы потребовать noexcept для деструкторов и move конструкторов.

Есть много вариантов как реализовать std::variant, у всех есть свои недостатки. Мне нравилась версия «требовать noexcept default constructor для хотябы одного типа». Но у этой версии большие проблемы с юзабилити, так что std::variant с valueless_by_exception() намного более юзабельный.

Не в курсе, к сожалению. Реализовывал свой велосипедик на эту тему, чтобы работал на GCC 4.9 и не аллоцировал память. В результате пришёл к двум ограничениям — noexcept destructor и noexcept move constructor. На их основе можно делать variant который или будет всегда в валидном состоянии, или уронит программу std::terminate. Оба ограничения как по мне вполне адекватные. Кидаться исключениями из деструктора нехорошо, а из мув-конструктора — просто глупо. Кстати, noexcept default ctor в таком случае не нужен.

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

Вот кстати не могу представить throwing move. Подкинете пример?

По-моему, аллокация памяти там сильно лишняя. Почему не могут просто отдать буфер? Ведь, по сути, recursive_wrapper почти то же самое, что и unique_ptr.

Если без неё, то становится намного хуже. recursive_wrapper отличается от unique_ptr тем, что не должен хранить nullptr. По смыслу recursive_wrapper — это ссылка, а не указатель.

Если разрешить ему хранить nullptr и кидать исключение при разименоввывании (а его разименоввывание происходит внутри variant и скрыто от пользователя), то variant теряет never-empty guarantee и иногда начинает хранить пустой recursive_wrapper. В итоге получается нечто среднее между boost::variant и std::variant, чего всячески хочется избежать.
Комбинация structured bindings и if (init; condition) очень вкусно смотрится:

if (auto [x, y] = foo(); y == something) {… }

Как я понимаю, переменные, объявленные в секции init, существуют и внутри else тоже?
Да, внутри else тоже существуют. А ещё эта конструкция применима и к switch:
switch (auto [x, y] = foo(); y) {
case 1: x += 10; break;
// ....
default: x = 0;
}
Хм… А до такого когда-нибудь доведут, интересно:
switch (foo()) {
case [true, result]:
do_something(result);
break;
case [false, _]:
LOG(error)
Хм… А до такого когда-нибудь доведут, интересно:
switch (foo()) {
case [true, result]:
    do_something(result);
    break;
case [false, _]:
    LOG(error) << "Shit happens!";
    break;
}


Кстати, а плейсхолдеры добавили? Желательно что-нибудь минималистичное вроде того же "_", а не «std::structured_bindings::paceholders» 8)) И алиасы нподобие хаскеллевского «pair@(first, second)»? Понятно, что это сахарок, но без него таки не так сладко будет.

PS: прошу прощения, в прошлом комментарии что-то с форматированием стряслось…
так можно же писать using std::placeholders;
Ну тогда уж using _ = std::unused. И, к слову сказать, ещё вот какую-нибудь такую штуку было бы приятно иметь a-la designated inits:
auto [st_size: sz, st_mode: mode] = fstat_wrapper(fd);
if (S_ISREG(mode) && sz > 0xfffffffful)
    std::cerr << "Ooops.\n";
UFO just landed and posted this here

Так уже можно, используя std::tuple и новую возможность вывода аргументов шаблонов для классов:


    if ( auto [x, y, z] = std::tuple(foo(), bar(), baz()); y == something ) { }
Очень интересно влияет ли развитие Rust на идеи участников комитета и обсуждается ли он? Да и вообще очень волнительно как один из любимых языков будет развиваться когда рядом есть такой конкурент как Rust, да еще учитывая новости о том, что его начали использовать в Dropbox, переписывать на нем отдельные части в Firefox и т.д. Просто раньше как то все было проще и понятней, был C и С++, и практически подавляющее большинство задач системного программирования решалось на них, но теперь то все эти задачи можно точно так же решать и на Rust с его вроде как передовыми идеями, и что дальше?
Безобразное усложнение С++ волей-неволей заставляет смотреть в сторону Rust.
Судя по небольшому личному общению: они замечают тот уровень маркетинга, который обеспечивает себе Rust, но его фичи как таковые их не беспокоят т.к. большинство из них потребуют переделывания либо С++ либо стандартной библиотеки, а они не готовы ни к тому ни к другому.
С тем же успехом можно сказать, что к моменту выхода С++20 уже никакой Rust будет не нужен.
Шел 2196-й год… С++ праздновал свой двухсотый день рождения новым стандартом, а его всё хоронили и хоронили…
Как дельфист: добро пожаловать!
это уже впору называть каким-нибудь «синдромом флешплеера» — его убивают, а он все чето никак.
а Rust не будет конкурентом плюсам, пока к нему не будут разжеваны и задокументированы все шаблоны проектирования, иначе два из трех интересующихся будут отпадать в борьбе с компилятором.
UFO just landed and posted this here
ну, флешплеер всё-таки сдох
сдох-не сдох, но Block Plugins пока отключать рано
… новым двадцатитысячестраничным стандартом…
Что-то я уже не уверен что введение новых сущностей просто чтобы писать меньше строчек себя оправдывает.

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

Впитывая в себя куски из boost'а стандарт становится такой же беспорядочной помойкой — безумно распухшей коллекцией «прикольных фишечек».

string_view это как раз очень хорошо — но чертовски поздно. Как и array_view. Надеюсь, к 20-му году прикрутят. А должны были вкрутить ещё в самом начале, в крайнем случае в 11-й версии. Но не судьба.

Ну string_view как раз штука удобная и нужная, да и раньше ей пользоваться можно было, что я успешно и делал. А вот вещи типа "if (init; condition)" тоже настораживают. Может это, конечно, во мне консервативность говорит, но оно кажется далеко не самым частым частным случаем. Для сравнения for по диапазону из C++11 мне очень нравится, да и случай чуть ли не самый частый.

Какой кошмар!!! (Я в положительном смысле :). Интересно, а комитет изучал вопрос, сколько людей в состоянии изучить современный С++ с нуля, а не практикуя его постепенно в течении 20 лет?
Мне кажется, что пора уже заканчивать с этим и нужно садиться за написание книг, где подробно описывать как теперь все это использовать и самое главное, что не использовать из старых практик, пока они сами не забыли как правильно.

Это, вообщем-то, основная проблема. Сейчас мы можем втянуть студентов в С++ только силой, т.к. добровольно никто на нем писать не будет — сядут за C# или Java, сделают свое приложение, начнут его продавать. А в C++ остались те кто, как я, слишком долго сидел в этой теме и имеет некоторые априорные знания о том как все было 10-15 лет назад, и как проэволюционировало.

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

Слушайте, я вот недавно в Сан Фран ходил на встречу SG14, и там один человек на полном серьезе предлагал встроить С++ package management в язык (!!!). Хотя на дворе 2016 год и идея внешнего описания зависимостей уже проработана и испробована в Cargo, NuGet и так далее. То есть даже в C++ Working Group есть люди которые далеки от понимания того, что творится в мире разработки.

Это, простите, капец. По-моему, это PL/1 v2 уже какой-то.
Хотя, с другой стороны, заставить всех использовать единый формат пакетов и проектов можно только жёстко впилив его в стандарт. Но этого не будет никогда — потому что MS, Google, GCC team будут вечно тянуть одеяло на себя.


/fanboy mode on
Хочу только одну вещь. Поддержку в Rust'е импорт C headers из коробки. После этого "два крестика" покатится cо всё нарастающей скоростью.

Хочу только одну вещь. Поддержку в Rust'е импорт C headers из коробки.

Мне кажется, усложнять язык для этого нет нужны, лучше доработать bindgen: https://github.com/crabtw/rust-bindgen#plugin

Там ЕМНИП самая большая проблема осталась — макро константы. Но не будем здесь разводить оффтоп.

Когда Степанов выступал в «Яндексе» (видео доступно), он рассказывал про комитет, и говорил, что там очень много людей, которые просто за счёт компании едут посмотреть на Париж и другие места, где проходят заседания комитета. Дословно было сказано: "У них нет знаний, но зато есть мнение.", а работа комитета устроена так, что каждое предложение, нужно изучить и аргументированно утвердить или отказать, т.ч. бюрократия сильно мешает.
А опытных разрабов почему не посылают? Работать будет некому?
Видимо едут много халявщиков от компаний (с секретаршей), до понимающих людей путёвка не доходит! :)
UFO just landed and posted this here

Для С++ я советую финансовый сектор в крупных городах — Лондон, Нью Йорк, Чикаго.

Вот только попасть в НЙ или Чикаго из России нереально :)

С чего вы взяли? Попасть куда угодно — реально если у вас есть навыки.

Как, позвольте узнать? На рабочей визе лотерея с конкурсом 20 индусов на место, на «гринке» опять же лотерея с невнятными перспективами. Гарантированного варианта нет. Переводом из Европейского офиса только если, и то не уверен.
UFO just landed and posted this here
Лично мне виза по учёбе несколько поздновата, но другим информация будет полезна :)
UFO just landed and posted this here
У индусов квоты на въезд много ниже и выбираются моментом, а в иной год вообще полностью закрывают набор из Индии. В этот момент девелоперам из менее населённых стран получить H-1B становится гораздо легче.
Кстати интересный момент, не слышал о таком раньше, спасибо за подсказку :)
Стоп, я похоже пал жертвой склероза: квоты по странам — это для гринкарты :( Для рабочей визы есть только две квоты — общая (65000), и для тех, кто закончил какой-нибудь американский университет (20000).

Но вообще, если вы найдёте работодателя-спонсора, то шансы достаточно велики, чтобы пробовать.
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
UFO just landed and posted this here
Лучше напишите статью… но если никак, то хотя бы в личку напишите, пожалуйста…
«Ну ты бы хоть лотерейный билет купил»

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

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

А как они зависят? На обычных шаблонах, кажется, без проблем делается.
Таскать везде begin и end вместо одного range — неудобно.
Тот же string view — это же, по сути, range, но почему-то только для строк?

Ranges это не только добавление пары перегруженых методов к алгоритмам. Это еще и очень тесная интеграция с концептами и переписывание большей части снатдартной библиотеки. Так например метод all_of в данный момент выглядит вот так:

template<class InputIterator, class Predicate>
bool all_of(InputIterator first, InputIterator last, Predicate pred);


С Ranges он будет выглядеть вот так:

template<InputIterator I, Sentinel<I> S, class Proj = identity,
    IndirectCallablePredicate<projected<I, Proj>> Pred>
bool all_of(I first, S last, Pred pred, Proj proj = Proj{});

template<InputRange Rng, class Proj = identity,
    IndirectCallablePredicate<projected<iterator_t<Rng>, Proj>> Pred>
bool all_of(Rng&& rng, Pred pred, Proj proj = Proj{});


Оценить масштаб изменений можно почитав proposal: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4569.pdf

А это как-то мешает сейчас ввести ranges как простой шаблон с begin и end, а потом (если это потом настанет) уже расширить его концептами?
Переделок будет даже меньше, чем делают сейчас, например, с параллельными алгоритмами.

Одна из особенностей Range — begin и end могут быть разными типами (в примере выше это можно увидеть). Без этой возможности реализация значительно усложняется. А при её наличии ломается совместимость с предыдущими версиями стандартной библиотеки.
Я большой фанат C++, но когда я читаю очередной черновик стандарта, мне всегда вспоминается этот комикс:
комикс про 4096 процессоров

Да, есть хорошие и удобные фичи. Но дофига нужного до сих пор нет!

Навскидку:
1) нормальные, черт возьми, строки!
2) модули
3) полиморфные лямбды
4) xml, json и прочая сериализация/десериализация из коробки
5) в мире существует сеть, и пора бы уже о ней узнать!
6) ну и еще кучу всего, ночью уже сложно вспоминать…
UFO just landed and posted this here
UFO just landed and posted this here
А в каком контексте текущие лямбды не полиморфны?
1) работа со строками это грусть, но это скорее претензии к STL, а не к языку.
2) ну все ждут и все хотят, но это такая глобальная тема, что комитет не хочет сделать какашку, от которой следующие 30-50 лет люди будут страдать.
3) а сейчас что не так
4) дайте рефлексию, и все это будет не нужно. А черновиков по рефлексии несколько уже есть.
5) вот тут просто +100500. Хотя бы ip-сокеты/listener-ы стандартизировали.

5) тут можно много копий поломать. К примеру, проакторный Asio я бы не сильно хотел видеть в качестве реализации сети в стандарте. Плюс, говоря о сети, нужно думать и о эффективной работы, неблокирующем режиме и мультиплексировании… А вот тут некая система Windows выделяется своим IOCP (без спора — что эффективнее)...

Работа над сетью идёт, на данный момент самым жизнеспособным предложением является предложение на основе ASIO, но правиьно переработанное http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/n4575.pdf.

Очень много интересов сошлось на этом proposal. Все хотят сеть, но у всех разные желания: производительность, отзывчивость, простота, сопрограммы, единый интерфес с многопоточностью/stl, расширяемость и т.д.

Всей душой болею за это предложение и при том не я один. Должно получиться очень красиво и правильно, не не известно к какому году.
Спасибо большое за ссылку, очень интересно!
Это, конечно, интересные фичи. Только зачем они в стандарте?
А где еще модулям и рефлексии быть?
Без модулей и так неплохо. А кому нужна рефлексия, тот знает, где скачать Java.
UFO just landed and posted this here

6*) нормальная функциональная поддержка для контейнеров чтобы можно было писать:
m.filter(...).map(...).reduce(...)
(но мы знаем, что это невозможно, пока не будет ranges, а ranges каким-то образом завязаны на концепты)


6**) Вдобавок к (непринятой в 17м стандарте) возможности вызывать метод класса как method(object, arg), добавить аналог this для аргументов из C#, когда один из аргументов для функции можно написать через точку слева, как будто это вызов метода: arg1.func(arg2). Это позволит писать функции для работы с объектами, избегая огорода из скобок.


6***) Убрать неконсистентное требование того, что временные объекты обязаны быть константными — чтобы заработало вот такое: func(C()), где C() — временный объект, который принимается в функцию по неконстантной ссылке.
Потому что сегодня приходится размазывать это на две строки:
C c = C(); func(c);
чему не видно никакого оправдания.

6**) Вдобавок к (непринятой в 17м стандарте) возможности вызывать метод класса как method(object, arg), добавить аналог this для аргументов из C#, когда один из аргументов для функции можно написать через точку слева, как будто это вызов метода: arg1.func(arg2).

Этим занимаются Страуструп и Габриель Дос Райс, но предложению предстоит ещё несколько итераций доработки. Вот последний proposal на эту тему http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0416r0.pdf
По поводу if (std::lock_guard lock(m); !container.empty())
Не могу в данный момент проверить, но не должно ли if (std::lock_guard lock(m), !container.empty()) делать тоже самое уже сейчас?
В Вашем примере мьютекс захватывается и сразу освобождается перед сиквенс поинтом — оператором,
В случае if (std::lock_guard lock(m); !container.empty()) lock живет в течение всего if стеймента
Вот только такой if коварен. Если в for заменить точку с запятой на запятую, то будет ошибка, а если в новом if — будет оператор запятая.
Не будет. Оператор запятая тут недопустим. Вы должны либо описать ровно одну переменную (C++14), либо поставить-таки точку с запятой.

Да, действительно. Я заставил пример собраться, но о семантике не подумал.

Шел 2016 год, а я так и не мог написать в программе std::optional; (ага, я в курсе что через пару лет заработает).
Зато постоянно добавляют кучу адовой эзотерики. Если раньше я мог сказать, что знаю С++, то теперь уже точно нет.

Интересно, помогает ли все это это языку? Если 10 лет назад на нем писали почти всё, то теперь он скатывается в нишевые направления — 3D движки, OpenCV, микроконтроллеры и немного десктопного Qt (сужу по заказам на UpWork).
Лично для меня, как стандартный C++/STL был непригодным к использованию 10 лет назад, так он и остается до сих пор (Строки, работа с файлами, сеть, потоки и т.д.). Даже долбаное кросплатформенное приложение с нативным GUI интерфейсом невозможно создать (когда там графический интерфейс появился, в начале 90х?). Утешает только Qt.
Вы забыли про браузеры, современные игры, высоконагруженые сервера, оффисные пакеты, программы для 3d моделирования, потрошки Андроида.
Браузеры, офисные пакеты, 3d моделирование и прочие десктоп-приложения вполне успешно пишутся на C# и Java.
Игры тоже.
Сервера гораздо проще не высоконагружать, а горизонтально отмасштабировать, купив железа. А написать на языке, в котором как минимум строки Юникод поддерживают, не говоря уже о встроенной поддержке БД и т.д.
Просто в рамках самообразования, можно посмотреть на браузер целиком написанный на С# или Java? Ну и сервер, выдерживающий проблему C10k?
Давайте говорить про доступные на рынке работы. Количество браузеров к общему количеству написанного ПО ничтожно мало. Я не знаю, на чем написаны конкретные браузеры, но не вижу большой проблемы написать их на C# или Java.
Сервер с C10k есть прямо в статье https://en.wikipedia.org/wiki/C10k_problem это некий MigratoryData на Java на 10–12млн подключений.
Как-то странно у нас диалог пошёл. Сперва Вы пишите:
Браузеры… вполне успешно пишутся на C# и Java.

затем:
Я не знаю, на чем написаны конкретные браузеры, но не вижу большой проблемы написать их на C# или Java.
Так пишутся или «не знаю, но обсуждаю»?
Про С10к Я могу привести гораздо более развёрнутую статью с французской вики где про MigratoryData даже и не сказано. Что такие сервера есть, я уверен, есть вполне успешный сервер на питоне умеющий в С10k, но в основе они всё равно обращаются к чисто системным вызовам epoll/kqueue/iocp и так далее, но это не часть «стандартной» Java, почему я и попросил ссылку. Да и MigratoryData целиком коммерческий, может поэтому по нему очень мало информации в интернетах, в отличии от остальных (с десяток, не меньше, и бесплатных).
Немного не в курсе — в JavaFX браузер нативненький или java-based? И ещё куча всяких embedded-браузеров. Да это не браузер общего назначения… но в браузерах общего назначения итак не протолкнуться.

Насчёт серверов общего назначения — на Java, скорее всего, нет. Есть различные контейнеры приложений (tomcat/jetty/...), сколько они держат подключений на практике — не знаю, не интересовался. С учётом того, что основная их задача — не отдача статики, а отработка запроса в приложениии — проблемы раньше упрутся в особенности приложения.

Ну а сервер общего назначения, выдерживающий c10k я знаю один, но он не на плюсах а на голом C написан (nginx). На плюсах есть аналог?

Сервера разные, вот вам пара на C++: Nimble и EvoStream, но если посмотреть внутрянку (по импортируемым симвалом), то там беркли сокеты и poll/kqueue.

boost.asio дёргает внутри себя
(epoll на Linux 2.6, kqueue на FreeBSD/MacOSX, Overlapped IO на MS Windows)

И что? Asio там не используется, Nimble — косвенное заключение да и за чаем разработчика спрашивал, а исходники EvoStreamer до того как он стал закрытым доступны: crtmpsserver, там тоже нет Asio. Правда, думаю, сейчас Evo от своего прародителя далеко ушёл.


А по своему опыту: нужно было написать молотилку запросов HTTP (много мелких) Asio раскачать сильно не получилось, упирался в ~250к RPS, тогда как на libev (у него встроенный C++ интерфейс есть) запросто получилось около 600к RPS. Правда это на 1k подключений, на 10к снизилось где-то в полтора-два раза, на обоих.


Минус решений отличных от libuv и asio: для Windows, по сути, приходится писать свой код.


Ну и ещё, Asio и libuv сильно обмазывают epoll снаружи, что бы его использование походило по интерфейсу на IOCP

вот тут статья от mail.ru про c10k и boost.asio
https://habrahabr.ru/company/mailru/blog/191756/
Есть не совсем аналог. Но несколько лет назад он раза в 3 работал быстрее, чем nginx.
https://github.com/mamchits/phantom
На нем еще построена тулза для нагрузочного тестирования Яндекс.танк.
Нет, нет, нет… заберите всё это себе… Никаких браузеров на Java и C#, кстати где вы их взяли? :)
Хм… а чем вам не нравятся браузеры Java? Небольшие эмбеды в различные java-приложения… удобно же? Согласен, что они добавляют свои нюансы (в них не втюхивается столько сил, сколько в вебкит и файрфокс, поэтому они несколько отстают от стандарта), но их и используют только в определённых задачах (различные плюшки в тех самых java-интерфейсах; различные генераторы, например pdf).

Вообще я был бы рад, если бы они развивались, но нужда сообщества в них достаточно мала, также как и интерес крупных компаний :(
Помню когда начинались «одноклассники», был С#, потом Java и какие были тех. проблемы, когда пошёл взрывной ростаудитории и оказалось, что стоимость железа будет просто огромна, да и ЦОД таких практически не было.
Про потрошки Андроида — назовите меня фанатом, но таки на С. Ибо есть высокоуровневая Java, и лично я не вижу смысла прятать под капотом ещё один высокоуровневый язык программирования. Выглядит как костыль.
Первая же ссылка из геррита андроида ведет на плюсы:

https://android-review.googlesource.com/#/c/247370/5/compiler/optimizing/code_generator.cc

В андроиде на самом деле почти весь user-space на плюсах.
Лучше сюда посмотрите. Это не какой-то там комилеро-генератор, а, на минуточку, начальный загрузчик. То есть то, что стартует в самом-самом начале, до любой программы.

На C в Android'е — только некоторое количество legacy-кода (взятого часто из разных BSD).

Вообще весь Android — это немного «театр абсурда»: почти весь Android — написан на C++, большинство популярных программ — тоже. Но взаимодействовать им приходится через Java'у обходя кучу костылей, нужных для этого монстра. Вот что бывает когда PR ставят выше технической целесообразности… с другой стороны если бы не PR, то Android фиг бы «взлетел»: его ранние версии, по большому счёту, были весьма убоги, если бы не волшебное слово «Гугл», то не факт что его бы кто-либо сейчас ещё использовал…
С моей точки зрения — потрошки Андроида на плюсах — это не есть хорошо. Вот это я и хотел сказать в своём комменте. То, что они по факту написаны на плюсах — я знаю.
Даже долбаное кросплатформенное приложение с нативным GUI интерфейсом невозможно создать

Единственный язык, который я вспомнил с ходу, со своей собственной реализацией кроссплатформенного GUI — это Java. И, знаете, как-то оно меня тоже не радует (как пользователя). Уж лучше Qt или другой «универсальный» тулкит.
Раньше главные претензии были, что мало функций, маленькая стандартная библиотека, нужно больше всего, и теперь когда это пытаются дать, начали раздаваться крики «горшочек не вари». :)
И оба мнения правильны, что характерно. Библиотеки нужно оформлять как отдельные подстандарты — и реализации смогут пречислять какие из них поддерживаются. Да и с языком тоже самое: Fixed point существует как отдельная сущность от всего остального — что не мешает его использовать тем, кто он нужен.

Это реально "горшочек". Одно только внедрение аналитической геометрии в стандарт. Хотя ей самое место в отдельном пакете. Т.е. в стандарт тащат много, но не всегда то, что реально нужно.

UFO just landed and posted this here

А я не говорю, что аналитическая геометрия это плохо. Я говорю, что ей место в отдельной либе. Пусть она поддерживается комитетом, не вопрос. Но отдельно. Иначе такими темпами в стандарт захотят 3Д-движок, физический движок, библиотеку акторов и что-нибудь ещё. И тогда стандарт будет не 1600 а 16000 страниц.

Другими словами, вы не хотите один документ с 16000 страниц, а хотетие 10 документов по 1600.

Мне кажется это вопрос оформления/вкуса/дизайна/скрипта-сборки-документа. О чем спор то? :)

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

Да не надо же вечно таскать, вполне себе выкидывают std::binary_function, например. Реализация какое-то время бдует содержаться, в этом проблема, да.

Проблема в том, что это просто тяжело осилить одним куском. Это примерно как God Class. Класс, отвечающий за всё и сразу. А помнить о всех тёмных уголках стандарта придётся — даже тем, кому эти мат. функции не нужны.

UFO just landed and posted this here
На мой взгляд, тут дело не в том, чтобы остановить поток лавы. Все эти разношерстные фичи толкаются разными разработчиками библиотек и они реально им нужны для макро и микро оптимизаций. Они также делают много обобщений и постоянно сталкиваются с дублированием кода и им нужно все это оптимизировать. У этих людей весь С++ загружен в «кеш». Т.е. они полностью погружены в потроха С++ и глядя на код видят результат компиляции. Я сам, когда долго пишу низкоуровневую библиотеку, перехожу в это состояние. Но когда начинаешь решать реальную бизнес задачу, «наверху», использую свои наработки, то все эти детали быстро улетучиваются. И что делать прикладным программистам в этом случае??? Тут нужно вырабатывать автоматизм, а с таким зоопарком это очень трудно сделать. Приведу пример:

Был сеттер:
void SomeClass::SetName(const std::string& first, const std::string& last);

Теперь, в новом стандарте, есть move сематика. Теперь в лоб, получается, что для того, чтобы работали идеи авторов стандарта нужно писать что-то типа того:
void SomeClass::SetName(const std::string& first, const std::string& last);
void SomeClass::SetName(std::string&& first, const std::string& last);
void SomeClass::SetName(const std::string& first, std::string&& last);
void SomeClass::SetName(std::string&& first, std::string&& last);

т.е., на лицо, логарифмический рост количества перегрузок функций.
Я понимаю, что нужно теперь писать вот так:
void SomeClass::SetName(std::string first, std::string last);

и компилятор сам разберется, но что бы это понять и убедиться что это работает, нужно столько сил и времени. В итоге имеем такие затыки через каждые 20 строчек.
> но что бы это понять и убедиться что это работает, нужно столько сил и времени
Просто: потому что copy elision 1. и так реализован в основных компиляторах 2. является требованием с++17.

> В итоге имеем такие затыки через каждые 20 строчек
Вот когда замерите, увидите что у вас программа 30+% времени перегоняет пустое в порожнее, туда-обратно копирует и жрет оперативку как хром, тогда у вас будет замечательный инструментарий в виде lvalue reference/rvalue/copy elision для оптимизации копирования и использования памяти. А заниматься микрооптимизациями, да еще и без четкого понимания как это всё работает — вредить себе и проекту.
По сути, все о чем мы тут рассуждаем и есть сплошные микрооптимизации. Это все базовые кирпичики размазанные тонким слоем и никого HotSpot-а в 30% в базывых примитивах в адекватном коде на С++ вы не увидите. С точки зрения высокоуровнего программиста, можно писать хоть на javascript. Ему С++ не нужен.
я немного про другое. Писать несколько лишних перегрузок функций, каждая из которых сэкономит всего по несколько процессорных тактов, займет больше времени, чем эти несколько тактов сэкономят за всё время жизни приложения.
Я согласен. Но, если не важны такты, то и С++03 достаточно, и все эти микрооптимизации интересны только комитету и чего мы тогда тут страдаем :)
потому что из 100 случаев в одном эти микрооптимизации таки принесут пользу
Это не так. Конструктор перемещения теперь присутствует, в том или ином виде, почти в любом классе и везде теперь придется учитывать возможности нового стандарта. Иначе все эти усложнения просто бессмысленны.
Нет. Во-первых, есть много сценариев, при которых компилятор вправе сделать placement конструктор вместо перемещения. Во-вторых, многие операции перемещения в stl легальны только если соответствующие конструкторы/операторы присваивания объявлены noexcept. В-третьих, как я уже писал, перемещающие конструкторы/операторы присваивания неявно создаются только для классов, у которых не переопределены копирующий конструктор/оператор присваивания/деструктор. В четвертых, везде, где у класса не определена соответствующая мув-семантика, компилятор использует копирующие аналоги.

Сценариев, где неявно используется семантика сдвига вместо копирования, не так уж и много и наткнуться на ошибки при их использовании попросту невозможно: это требует ручного некорректного определения мув-семантики в используемых классах.
Спасибо, я в курсе. Я не про корректность, я про то, что когда пишешь свои библиотеки и хочешь использовать преимущества современно С++, теперь, все это придется учитывать.
Все-таки перегрузки с const std::string&& бессмысленны. Достаточно иметь 2 перегрузки — const std::string& и std::string&&. Однако, если речь идет о сеттере, внутри которого значение захватывается по значению, то при наличии rvalue-ссылок можно передавать просто по значению:
void SomeClass::SetName(std::string first, std::string last)
{
    _first = std::move(first);
    _last = std::move(last);
}

Поскольку move очень дешев, то это будет практически оптимально для всех случаев:
foo->setName(first, last);
foo->setName(std::move(first), std::move(last));
foo->setName("Ivan", "Pupkin");
Так предыдущий комментатор именно это и написал. Если есть 1 параметр, то будет 2 перегрузки, если 2, то 4, если 3, то 8 (дял всех возможных комбинаций) и так далее.
Мой комментарий был о том, что практически всегда можно оставить один из вариантов, в зависимости от использования данных внутри функции — либо передавать по значению, если внутри метода сохраняются данные, либо передавать по константной ссылке. И не нужно большого числа перегрузок.
А зачем использовать один язык для _всего_?
По-моему у каждого языка есть свои плюсы и минусы и, следовательно, он подбирается исходя из требований решаемой задачи.
c++ отлично подходит, если нужно написать какую-нибудь высокопроизводительную и сложую систему, но зачем его использовать там, где есть более удобные инструменты, пусть даже это и отразится в меньшей производительности и большем потреблении памяти, когда это не является критичным.
UFO just landed and posted this here
С радостью помогу с написанием предложений по стандартизации подключений к базе данных. Но тут нужен достойный прототип.

Графику наврядли получится стандартизировать. Слишком большой выбор: есть Qt, WxWidgets, Gtk, EFL и многие другие.

Был proposal с добавлением Cairo для 2D-графики. Он довольно низкоуровневый (GTK, Firefox его используют под капотом) и достаточно кросплатформенный. Но не знаю, как он там продвигается.

Зачем языку, программы на котором нередко исполняются в средах где не требуется GUI встроенные средства для графики?
В отличие от многих новых языков перед С++ проблема привлечения новых пользователей стоит не так остро, поэтому особо снижать порог вхождения не требуется.
Для «простых смертных» есть куча других языков, которые сознательно стараются упростить процесс разработки (порой, правда, ценой производительности/гибкости/узкой специализации)

В первую очередь для обучения. Детей, школьников. А то они спрашивают "а как мне нарисовать черепашку?" и получив ответ с отсылкой к каким-то непонятным библиотекам, выбирают другой язык.

С++ не очень подходит для обучения, ИМХО, даже совсем.
Ну и в таком случае, надо отсылать к понятным библиотекам.
UFO just landed and posted this here
Ну я же не предлагаю совсем отказаться от GUI в С++, я говорю, что в стандартной библиотеке (которая должна создаваться из расчета, что ее API не будет меняться десятилетиями, и что она будет реализованна для множества платформ) GUI явно излишен.

Для графического интерфейса, в мире С++ есть решения. Тот же Qt.
Если нужен быстрый старт, то берем Qt Creator и вперед. Подозреваю что подключить Qt в других IDE тоже не особо сложно.

я раньше обычно для работы с БД использовал QtSQL модуль, раз уж приложение с графикой, сейчас просто подключаю libpq — и ну его нафиг — тот QtSQL. Т.к. мне доступны все возможности БД, библиотека отлично документирована, много примеров. Т.ч. не так всё страшно.
Можно сделаьт класс обёртку, с методами — а под капотом делать бекенды которые могут с любой БД работать, хоть mongo, хоть oracle
Объясните мне,
— что теперь каждые 3 года, когда вводят новые фишки в C++, миллионы строк кода готовых оттестированных кодобаз (библиотеки, игровые движки) должны кинуться обновлять свои сорсы под эти фишки, рискнув стабильностью своих продуктов?
так и представляю: миллионы коммитов в древних не тронутых файлах, где меняется самое простое допустим xx::yy::zz::iterator на auto.

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

— или предполагается совмещение стилей С++03 с новыми стандартами в одном продукте?
т.е. листаешь ты сорсы, в одном файле xx::yy::zz::iterator, в другом — auto. Очень всё лаконично же и в одном стиле, не код, а загляденье.
Принципиальных изменений в C++ не происходит. Происходит только медленное разрастание STL и добавление синтаксического сахара для увеличения простоты и уменьшения объёма кода.

Единственное фундаментальное изменение — это move semantics.
А так да, можно писать в стиле C++03.
Простота с STL не увеличивается, когда мультишаблонный тип занимает полэкрана в объявлении переменной.
boost'у это можно простить, потому что они выжали максимум средствами языка, но бюро стандарта сделали эти костыли стандартом.

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

Move semantics прочитал здесь. «гениально», стреляем себе в ногу дальше. Теперь каждый раз нужно лезть в класс, и смотреть, а нет ли у него move semantics внутри, чтобы знать, что этот класс нельзя использовать после копирования foo&.
нет ли у него move semantics внутри, чтобы знать, что этот класс нельзя использовать после копирования foo&

Я вас не понял, распишите пожалуйста проблему подробнее.
Касаемо языковых фишек: простота увеличивается за счёт использования лямбд (больше не надо писать классы-функторы), range-based for (чуть меньше кода), constexpr (вместо шаблонов и метапрограммирования). Понятность — за счёт явного указание override и final для виртуальных функций, nullptr вместо константы NULL, отказа от enum в пользу enum class.

auto считаю злом.

Замечание про move semantics не понял. Любой старый класс будет неявно поддерживать перемещение, если не указано обратное. И всё будет работать корректно, но до тех пор, пока конструкторы копирования и перемещения будут выполнять только то, что они должны, без побочных действий.
Класс будет неявно создавать перемещающий конструктор/оператор присвоения только в случае, если у класса не переопределены копирующий конструктор/оператор присвоения или деструктор. А их как правило переопределяют для нетривиальных классов.
Да, действительно. Я просто заметил, что практически перестал использовать явные конструкторы копирования и перемещения.
UFO just landed and posted this here
UFO just landed and posted this here
Использование auto — как использование паттернов. Есть люди, которые считают нужным притягивать за уши паттеры там, где они не нужны.

auto хорош для локальных переменных, возможно, некоторых приватных методов. Но нельзя допускать, чтобы публичный метод возвращал auto, кроме редких случаев, когда используются шаблоны и вывод громоздок или крайне затруднителен.
UFO just landed and posted this here
Не стоило это делать. Не повторяйте мой опыт. auto — это просто инструмент, который нужно использовать к месту — и тогда он бывает удобен.
Вообще-то в rvalue reference превращаются только rvalue. А 'foo& bar' — lvalue. Здесь как раз косяков нет. Хотите переместить именованное значение — std::move. Но если после него вы используете старую переменную — ССЗБ.
Если у меня уже отлаженная парадигма классов в сервере, зачем мне добавлять новые классы с непонятным извне поведением, которое приведет к ССЗБ?
Весь этот огород с move semantics, когда однозначно не понятно, в каких случаях класс копируется, а в каких перемещаются кишки, и тогда старая переменная не валидна для использования, потому что внутренний хендл переместили. И что тогда в каждую функцию File добавлять проверку на валидность хендла? Адская избыточность. Зачем эти усложнения?

В той хабра статье уповают только на использование динамической памяти там, где она мол не нужна.
Какие сейчас проблемы с памятью? У меня на сервере свой MM, предвыделенные чанки (расширяются автоматически) от 8 байт до 32кбайт с шагом по экспоненте, в неблокирующем ring buffer'e.
Выделить 8-32кбайт на хендл затрат проц времени для ММ около нуля, зато получаем более управляемый код. Это я имею ввиду использовать хендл в обвязке умного указателя.

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

Да почему непонятно-то? Как раз наоборот, все предельно просто.


"Кишки перемещаются" ровно в двух случаях:


  1. когда старое значение более не доступно;
  2. когда программист явно написал std::move

Если вы не будете использовать std::move — вы никогда не натолкнетесь на невалидные переменные.


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

Все просто: move semantics придумали чтобы сделать нормальные умные указатели. К примеру, uniqie_ptr без семантики перемещения нельзя было бы использовать в STL-контейнерах.

Все просто: move semantics придумали чтобы сделать нормальные умные указатели. К примеру, uniqie_ptr без семантики перемещения нельзя было бы использовать в STL-контейнерах.

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

Ничего не просто. При move, копирование все-равно происходит. Это не панацея, а всего лишь еще один уровень оптимизации. Если у вас класс имеет 100 полей move придется их все копировать. Т.е. RVO и Copy-Elision предпочтительней, а const& все еще нужен. Этот экспоненциальный рост количества перегрузок, при проектировании интерфейсов, не добавляет простоты.
если при муве происходит копирование, значит вы что-то делаете не так
Да конечно… :). Например в std::string, обычно, есть оптимизация, где маленькие строки, до 16 байт, хранятся в статическом массиве в самом std::string. Как, по вашему, должен быть реализован конструктор перемещения в таком случае?
Вот только это «обычно» относится к одной-двум версиям библиотек и с появлением С++11 я не уверен, что этот «финт ушами» сохранился. В С++03 были и реализации, которые строку хранили по частям, разбивая на блоки фиксированного размера, в С++11 появилось требование о непрерывности блока памяти, хранящего данные строки.
Я смотрел. Он сохранился. Более того, это теперь почти единственная оптимизация для строк которая есть на практике, т.к. требования к строке в С++11 таковы, что теперь даже COW невозможен и все реализации библиотек переделываются чтобы учитывать новые требования.
ОК, буду знать, спасибо!
В C++11 этот финт ушами только и разрешили делать. Начиная с C++11 все реализации строки с COW или хранящие строку по частям, или не держащие на конце '\0' — не являются валидными имплементациями.

И слава богам! Замена COW строки на строку со small-buffer optimization в двух абсолютно различных проектах давала прирост производительности более 10% (мой личный опыт). Знакомые из других проектов подтверждают прирост в производительности.

Для не верящих есть целая статья http://www.gotw.ca/publications/optimizations.htm
Получается, что в случае «длинных» строк, мы получаем overhead по памяти, за счёт не используемого буфера в те самые 16 байт? Или его начинают использовать в других целях (указатель на память в куче и т.п.)?
Оверхеда нет, начинают использовать буфер под указатели и размеры.

Если вы таскаете по стеку структуру на 100500 полей, вы делаете что-то не так. А мув служит для почти бесплатного перемещения контейнеров, у которых маленьая часть на стеке и большая в куче. Простой пример — вектор на пару сотен килобайт. Без мува, при отдаче владения в функцию, у вас будет копирование. Толстое. С выделением ещё одного куска на пару сотен килобайт и копированием всего содержимого. С мувом — старый вектор отдаст новому владение буфером. И будет "копирование" 1 указателя. С занулением его на старом месте.

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

Бесплатного для того кто использует, а для того кто пишет эти классы :)?

Что я могу сказать. Не нравится — не используйте. Как указывалось много раз выше, перемещение включается в конкретных, чётко описанных ситуациях.


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

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

Почти бесплатно.


Современная концепция состоит в том, что управление ресурсами должно осуществляться в специальных листовых классах. Это могут быть умные указатели или самописные классы. В этих классах да, придётся самому написать все 5 спец-методов (см "Rule of Five"). Но таких классов должно быть немного (по одному на каждый вид ресурса, причём для самых распространённых ресурсов "память" и "открытый файл" такие менежджеры уже реслизованы в стандартной библиотеке).


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


Эта концепция известна под именем "Rule of Zero".

Ох уж эти теоретики… хорошо, запомним. Будем стараться осваивать все эти современные концепции. Главное, чтобы они не менялись быстрее, чем программисты их успевали изучать.
Теперь каждый раз нужно лезть в класс, и смотреть, а нет ли у него move semantics внутри, чтобы знать, что этот класс нельзя использовать после копирования foo&.


Мне кажется вы не поняли move сементику. Проблемы никакой нет. Прочитайте еще раз до полного просветления.
Зачем обновлять сорсы под фишки? можно просто сказать, что поддерживается такая-то версия языка.

Не нужно кидаться и обеспечивать поддержку всего-всего на свете.

Как-то в сфере веба довольно часто всё обновляется, но живет же как-то эта сфера.
std::string::data(), возвращающий неконстантый char* (УРА!);
Может я не сталкивался просто, а что не так было с константностью этого метода? Вполне логично, что получая «сырые» потроха строки их нельзя менять, как мне кажется.
проблема в том, что некоторые неблагородные API (и майкрософт грешит этим чаще остальных) часто просят, например, wchar_t* вместо const wchar_t* даже когда не меняют строку.
Для таких неблагородных есть const_cast, зачем еще новый метод добавлять?
UFO just landed and posted this here
И хорошо что пахнет: сразу видно где у вас кривизна в API. А так — вы её просто будете вытаскивать дальше по стеку. И у вас тоже появятся функции, принимающие std::string& вместо const std::string&, но при этом строку не меняющие. Кому от этого лучше станет?

Мне вот интересно в какой версии C++ конструктор string'а станет наконец-то constexpr… В 20й? Или в 50й?

Как писал Джоел: Интересно, что историю развития C++ можно описать как историю затыкания дырок в абстракции строк. Уж не знаю, отчего бы не добавить к языку элементарный класс строчек.

Пока что наблюдение продолжает иметь силу :-)
UFO just landed and posted this here
Если передавать std::string, то будет лишнее копирование при невозможности перемещения при передаче параметра в функцию.
UFO just landed and posted this here
Да, в случае работы с сетью частая ошибка: уничтожить буфер до того, как он будет фактически отправлен. Тут действительно лучше скопировать — надёжнее будет.
UFO just landed and posted this here
> Мне вот интересно в какой версии C++ конструктор string'а станет наконец-то constexpr…
Если вы знаете, как сделать constexpr-конструктор для класса, владеющего памятью на куче, срочно оформляйте proposal! Это же столько дряни в компайл-тайм перетечет!
А что мешает создать объект, который будет ссылаться на память в секции .data?
Это будет std::string_view а не std::string.

std::string_view имеет в C++17 constexpr конструкторы и операторы, но часть операций зависит от CharTraits, где аналогичные операторы тоже должны быть помечены как constexpr.

То, что его нельзя будет затем ресайзить?

если говорить конкретно про std::string, то тогда надо будет добавлять флаг того, что строка ссылается на константную строку в памяти. Соответственно, при попытке модифицировать строку будет происходить отложенное выделение памяти, копирование, модификация и пр. Т.е. сделать constexpr string(const char *) таким образом в принципе можно, вот только string+string или другие тривиальные операции уже constexpr не сделаешь. Помимо этого все операции будут проверять флаг и сама строка вырастет в размерах. Получается размен шила на мыло.

Вариант 2: сделать конвертируемую в std::string constexpr-оболочку поверх const char*. Тогда оболочка-то будет constexpr, а сам string будет создаваться из неё в рантайме. Т.е. тоже бесполезно.
Был пропозал отдельный на fixed_string http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0259r0.pdf На сайте автора пропозала можно найти реализацию.

Кстати, из чистого интереса. std::vector, std::string научились конструироваться из сырого буфера и отдавать свой сырой буфер?

отдавать — вроде давно научились std::vector::data/std::string::data, начиная с С++11 метод data должен возвращать указатель на корректную нуль-терминированную строку.
The pointer returned points to the internal array currently used by the string object to store the characters that conform its value.
Both string::data and string::c_str are synonyms and return the same value.

http://www.cplusplus.com/reference/string/string/data/

Нет, я не про то. Я про возможность отобрать владение таким буфером и отдать кому-то ещё.

Такого нету, да. Достаточно специфичное требование, кстати, хотя я сталкивался несколько раз, когда подобное поведение было бы удобным.
string_ref не владеет буфером, поэтому можно её использовать в таких случаях.
Или нужно что-то наподобие unique_ptr, который принимает готовый указатель и владеет им, пока явно не отдашь (release)? Но зачем?

Отдать владение в какое-то API. Бывает необходимо. Сейчас аллоцируешь сам, копируешь и уже новое отдаёшь.

для таких целей скорее нужен std::unique_ptr<T[]>

С ним банально неудобно работать. Один из кейсов, пусть и редких — набить с помощью вектора массив данных и скормить вместе с владением какой-нибудь функции.

Капец, когда забривали всякие вещи, потому что они дублируют функционал и при этом замена была действительно лаконичной, объемы кода заметно уменьшались, а тут нате вам корявый if с инициализацией. Если уж хотелось что-то подобное, лучше бы сделали аналог using из C#, было бы куда полезнее, чем этот костыль.

Ну, реализовать using-то теперь можно без проблем:


#define using(x) if(x; 1)
Но это макрос, не красиво. Просто непонятно, зачем делать частичный функционал, а потом если захочется для while подобный функционал. Оно самом по себе как-то не так.

Для while такое уже есть, называется for :)

Ну а если я хочу именно while, чтобы подчеркнуть, что мне не нужен блок итерации внутри инструкции. По вашей логике и вместо if был уже for.

А вот это действительно странно, объявление переменных в условии это общее свойство if/switch/while/for, а расширили синтаксис только для if и switch. Причём добавлять в for может не захотели из-за изменения его структуры, а вот чего while пропустили непонятно.

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

Я не о i:


for (int i = 0; i < 10; ++i) ...

А о e:


for (int i = 0; error_code e = check_i(i); ++i) ...

Могли бы расширить (для единообразия, практической пользы тут не так уж и много) до:


for (int i = 0; error_code e = check_i(i); has_error(e); ++i) ...

(здесь e вычисляется и проверяется на каждой итерации)

«void get_vendor_from_id(std::string_view id) „

и тут же:
“Осторожно: string_view не гарантирует, что строчка, которая в нем хранится, оканчивается на символ '\0', так что не стоит использовать функции наподобие string_view::data() в местах, где необходимо передавать нуль-терминированные строчки.»

почему бы сразу не рассмотреть std::string get_vendor_from_id(std::string_view id)?
Оператор вывода в поток перегружен для std::string_view. Это значит что строчки не оканчивающиеся на '\0' всё равно будут корректно выедены.
вопрос про вывод в std::string
std::string умеет конструироваться от std::string_view. std::string копирет строчку из std::string_view и добавляет '\0' в конец строки.

std::string_view id{"Vasya Pupkin:Super Stuff"};
std::string_view vasya_sb = id.substr(0, id.find_last_of(':'));
std::string vasya{ vasya_sb };

assert(vasya == "Vasya Pupkin");
Почему же при такой любви Комитета к функциональщине, в стандартную библиотеку еще не внесли «джентльменский набор» из всевозможных apply, fold, map, zip, zipWith и т.д., создающих последовательности вызовов на этапе компиляции? Ведь все предпосылки уже есть, и часто приходится самостоятельно писать вещи для std::array или std::tuple с различной степенью кривизны. Планируется ли что-нибудь из этого в ближайшем будущем кроме уже внесённого apply для кортежей?
apply и make_from_tuple приняли в C++17
fold — в C++17 есть fold expression наподобие variable_pack +…
zip, map — нет изкоробочного, готов помочь с написанием proposal если вам интересно
Согласен с высказываниями выше насчет строк и т.п. Действительно перегрузили язык уже и так. Пишу на с++ постоянно. Но сил уже нет изучать новые хитрости и премудрости. Qt очень и очень радует. Есть еще Poco Library для некоторых вещей. В принципе вот куда надо смотреть. Язык надо упрощать, чтобы было приятно на нем писать.
Определённо не хватает включенных в язык графических модулей, как в Борландовском Турбо Паскале. Ну чтобы новичкам было легче вливаться.
Ну и компоненты, как в Делфи.

Злой тролль-сишник так и не осиливший плюсы.

Пропозал по графике на основе Cairo уже в процессе.

Радует что при использовании structured bindings можно будет проще по мапу итерироваться, а не ковырятся с first/second

for(auto [key,value]: my_map) {
}
Не верится, что уже в следующем году всё это будет законно. Особенно мне нравится первый пункт — constexpr if. Я пока не знаю точно, где и как я это буду использовать, но уверен, что эта фича станет моим новым фаворитом.
Есть мнение — на собеседованиях вопросов прибавится. Код останется прежним.

Для каких переменных используется именование с подчеркиванием на конце? Например, valuesmutex.

Обычно такой convention используют для private элементов.
А с новыми плюшкками получится сделать обмен переменных, написав [a, b] =[b, a] (или еще auto добавлять надо)?
А смысл? Чтобы использовать в процессе обмена две временных переменных вместо одной?

Интересно что люди одновременно хоронят С++ за лишние фичи и за из отсутствие. Причем одни и те же фичи одновременно ругают и хвалят куча людей.


Кто не верит в комитет — вступайте и действуйте ИМХО. Кто не верит в С++ — развивайте/пользуйтесь альтернативами

«Есть всего два типа языков программирования: те, на которые люди всё время ругаются, и те, которые никто не использует.»
— Bjarne Stroustrup.
UFO just landed and posted this here
Ищите положительные стороны, изучив всё эти фишки и умея их применить на практике эффективно можно стать очень ценным и высокооплачиваемым специалистом :)
А может кто-нибудь, кто лучше в разбирался в теме, рассказать о проблемах с концептами в плюсах? Просто я ещё понимаю, когда речь идёт о полноценном языке контроля AST — это понятно почему трудно. Но мне всегда казалось, что в концептах как в фиче нет ничего сложного хотя бы потому, что она никак не влияет на кодогенерацию (если не рассматривать возможные оптимизации, которые компиляторы смогут делать благодаря концептам). Фактически, это что-то вроде встроенного в язык редактора правил для статического анализатора… Или я ошибаюсь?

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

Ух ты, погуглил — точно! Где-то очень вскользь встречал что будут такое делать — но как-то мимо прошло, надо же. Спасибо, смотрю вот теперь чего там в gcc наделали. Первый же пример впечатляет — ограничение на перечень методов объекта-аргумента. Я так понимаю, так же и с шаблонным аргументами можно?

Быстрее бы до ума довели.
Вот смотрю на «рост» С++ и всегда удивляюсь — почему такую простую вещь, как for… else никак не реализуют? Неужели это никому не надо?
Представим ситуацию поиска элемента где-либо (например, в массиве):
item a = ...;
for (...)
{
  item b = ...;
  if (a == b)
  {
    // We've found the item
    do_something ();
    break;
  }
}
// We are here in both cases when we've found <a> and when we haven't.


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

Проблема курицы и яйца: for...else люди не используют потому что не знают, а раз не знают — то и в стандарт добавить её некому…
С новым синтаксисом, насколько я понимаю, можно будет написать как-нибудь так:
if (auto result_it = std::find(std::begin(container), std::end(container), a)
    ; result_it != std::end(container)) {
  do_something();
} else {
  ...
}
Да, если речь идет о простом поиске в контейнере — в stl есть варианты (даже сейчас). Но меня интересует именно конструкция языка. Например, я делаю итеративные расчеты с ограниченным количеством итераций (лимит в for), и если на какой-либо итерации я достигаю заданной точности, выхожу из цикла досрочно (break), если же за определенное количество итераций достигнуть требуемой точности не получается, я должен предпринять какое-либо еще действие. Понятно, что в таком примере один лишний if на ситуацию вряд ли повлияет, но по мне это именно тот случай, где задача едина для всех платформ и компиляторов и четко формализована.
Можно завернуть код в «фиктивную» лямбду c мгновенным вызовом и выходить не break'ом, а return'ом:
[&]{
  for (...) {
    ...
    if (...)
      return;
  }
  // Else part
  ...
}();
Если можно завернуть поиск в функцию, можно (будет) использовать std::optional, у которого как раз семантика «значения может не быть».
Можно, конечно. Варианты есть всегда)
Но для чего вводят if (init; cond)? Ведь и без этой конструкции варианты есть. Вот так же и тут)
> Например, я делаю итеративные расчеты с ограниченным количеством итераций (лимит в for)
ну и итерируйтесь не до end(), а до advance(begin(),N). Для random access итераторов (например, в векторе) можно даже писать begin()+N.

Если там какая-то совсем сложная логика, то проще либо на функции разбить (и возвращаться через return), либо (на крайний случай) булевый флаг завести. И то вызовет меньше вопросов

А если уж и заводить такой функционал, то назвать как минимум не else, а interrupted/finished, например
Какое именно слово использовать для такой конструкции — не столь важно. Вопрос в том, почему бы ее не ввести вообще, если уж дошли до if (init; cond)
разница в том, что if (init; cond) очень удобен, например, для раннего возврата, проверки защищенных мьютексами переменных (навскидку). И им гарантированно будут пользоваться. Что до for… else — я о существовании такой конструкции узнал только сейчас, хотя уже кодил на питоне
К слову, у вас есть идея как можно ввести эту фичу, не добавляя новых ключевых слов и при этом не сломав совместимость с подобным кодом:
if (...)
  for (...)
    one_code_line_action;
else
  ...
Справедливое замечание)
Навскидку могу предложить такие варианты:

1. Ввести новое ключевое слово. Не самый лучший вариант, однако, например, в С++11 появилось же auto. Вполне возможно, что раньше оно использовалось где-то в программах.

2. Использовать комбинацию ключевых слов, например:
for (...)
  {...}
for else
  {...}


3. Использовать >> или ->. На мой взгляд, внешне будет неплохии решением:
for (int i = 0; i < 5; ++i)
  if (get_byte_from_stream () == value)
    break;
>>
  send_byte_to_stream (value);

...

for (int i = 0; i < 5; ++i)
  if (get_byte_from_stream () == value)
    break;
->
  send_byte_to_stream (value);


4. Использовать ключевое слово continue. По текущему синтаксису оно используется так:
continue;


Здесь же будет

continue statement

for (int i = 0; i < 5; ++i)
  if (get_byte_from_stream () == value)
    break;
continue
  send_byte_to_stream (value);


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

Вы бы лучше бы какой-нибудь decltype вспомнили…

А насчёт комбинации ключевых слов можно своровать подход у Ады и использовать or else (или даже просто or).

P.S. Вы не поверите, но и and и or и даже not — в C++ являются ключевыми словами!
auto было ключевым словом с 70х годов, однако.

эх, забыл, каюсь) думал про decltype, но auto же короче)

Ну, на самом деле, сейчас (лично) мне нравится больше вариант continue либо >> (->). Но, по большому счету, это все равно ничего не изменит)
Да, на счет or, and и not — все верно, в стандарте они есть. Но вот только, например, MSVC2012 ничего про них не знает, позволяя написать такое:

int or = 5;
int and = or + 1;
and++;


MSVC, конечно, далеко не истина в последней инстанции, но это означает, что где-то могут быть программы, использующие такие имена.
  1. Выход из вложенных циклов без goto планируется?
  2. Планируется ли 'continue' блок для for/while, опять же, чтобы избежать goto и отличить нормальный выход из цикла от break?
Согласен, тот же break сейчас используется без параметров, можно было бы ввести
break n;

где n — число вложенных циклов, из которых надо выйти (и, например, 0 — для выхода из всех циклов, сколько бы их не было).
так это сложнее читать чем goto
Я лично (так как начинал программировать с ассемблера) никогда против goto не был)
Когда стал изучать С++ (С), мне достаточно успешно внушили, что лучше заводить флаг и пару ифов, но только не goto (что типа компилятор разберется и оптимизирует, а читать будет легче). Потом посмотрел исходники больших проектов и увидел goto там. С тех пор использую сам при необходимости без особых зазрений совести. Но встречал людей, для которых goto — как начало третьей мировой войны.
Но встречал людей, для которых goto — как начало третьей мировой войны.
Угу. При этом те же самые люди без зазрения совести используют, switch, break, continue — и канючат на тему «расширения их функциональности».

Карго культ какой-то. Как будто проблема goto — не в усложнении логики программы, а в том, что это слово портит карму.

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

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

Это ещё рефакторить менее удобно. Добавился цикл — надо будет посмотреть не используются ли внутри break/continue n. Лучше уж с именованными метками.

Не думаю, что это хорошо бы читалось. Лучше сделать как в Rust, где можно отметить цикл меткой и использовать break 'label.

Еще до Rust так было сделано в Java.

Ничем, в этом и плюс. Читабельность страдает когда goto используют много и бесконтрольно, а в данном конкретном кейсе goto наоборот самое читаемое решение.
А в чём вообще читабельность вложенных циклов? Это изначально «попахивающее» решение. Ну а вообще на коротких циклах читабельность страдает не сильно. Вот на больших и толстых… но они уже своим существованием затрудняют читабельность и добавление break label; ничего не ухудшит (label маркирует только уровень, до которого выходить… иначе говоря этот тот самый break count; только визуально более удобный и не умирающий при добавлении очередного уровня вложенности)

По-поводу конструкции if (init; condition) .... Почему не сделали как в некоторых других языках, например, вот так: let { init; } if (condition) ... или if (condition) ... where { init; }?

let… where

что бы ключевые слова новые не вводить?

Неясно, чем


let { init; } if (condition) { ... }

хоть немного лучше, чем сегодняшнее


{ init; if (condition) { ... } }

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


А where в хвосте — вообще жуть.
Это надо будет мотать в конец блока чтобы посмотреть, что же там за переменные в начале.

Тогда было бы логичнее сделать отдельное выражение let (init) something, которое было бы семантически было бы эквивалентно { init; something }

Тогда можно было бы использовать его не только для if и while, а в любом подобном месте. Скажем, в примере с захватом мьютекса мне может и не надо ничего проверять, я просто хочу захватить мьютекс, выполнить какое-то действие, а потом мьютекс отпустить.
let (std::lock_guard<std::mutex> lock(m)) if (!container.empty()) { // do something }

let (std::lock_guard<std::mutex> lock(m)) { // do something }
Вторая строчка эквивалентна простому:
{
  std::lock_guard<std::mutex> lock(m);
  // do something
}

Цель же введения этого нового способа записи в стандарт в банальной экономии строк кода.
Тут же в другом фишка. Иногда (и не так редко, как кажется) требуется, чтобы область действия lock'а совпадала с областью действия оператора if. Находилась в рамках его скоупа. Любой «двухстрочный» эквивалент не соответствует этой хотелке. Вот другой пример на это же:
if (ResultCode rc = DoSomething(); rc.Failed())
{
// обрабатываем ошибку, отваливаем
}


В рамках текущего стандарта это выглядит так:
ResultCode rc;
if ((rc = DoSomething()).Failed())
{
// Обрабатываем ошибку
}

Довольно, как это говорят, ugly. Предвосхищая вопрос. Такие конструкции могут использоваться в библиотечных «обёртках» над стандартной обработкой ошибок, логированием и т. п. То есть типа:
CHECK_SUCCEEDED_RETURN(DoSomething()) << «Приключилась адская хрень»;
«Автоматическое определение шаблонных параметров для классов»

интересно, как выкрутились, т.к. Страуструп декларировал:
Язык программирования С++ 386 стр.
«Обратите внимание, что параметры шаблона класса (в отличие от шаблона функ-
функции) никогда не выводятся. Причина заключается в том, что гибкость, обеспечивае-
обеспечиваемая наличием нескольких конструкторов класса, во многих случаях является непреодолимым
препятствием на пути такого выведения, и еще в большем числе случаев
выведение неоднозначно. Специализация предоставляет механизм неявного выбора
из различных реализаций класса (§ 13.5).»
Или из 4го издания стр. 686

Note that class template parameters are never deduced. The reason is that the flexibility pro-
vided by several constructors for a class would make such deduction impossible in many cases and
obscure in many more. Instead, specialization (§25.3) provides a mechanism for implicitly choos-
ing between alternative definitions of a template. If we need to create an object of a deduced type,
we can often do that by calling a function to do the deduction (and creation). For example, con-
sider a simple variant of the standard library’s make_pair() (§34.2.4.1):
template<typename T1, typename T2>
pair<T1,T2> make_pair(T1 a, T2 b)
{
return {a,b};
}
auto x = make_pair(1,2);
auto y = make_pair(string(«New York»),7.7);
// x is a pair<int,int>
// y is a pair<str ing,double>
Выкрутились вот так:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r2.html#uec
Грубо говоря, принцип аналогичен вызову функций, только для конструкторов.

Необходимость же такой возможности возникла из-за лямбд, тип которых в явном виде записать невозможно.
Есть новости по С++17 и связанным вещам:

Мы организовываем 5 октября 2016г открытую встречу российской рабочей группы по стандартизации С++: поговорим о перспективах С++, расскажем об успехах, новинках, толкнём мозгодробильную речьрасскажем о новых техниках в мета-программировании, выслушаем ваши предложения и замечания к C++17… + многое другое.

Подробности: Открытая встреча рабочей группы по стандартизации С++
А формата видеоконференции/телемоста не планируется? И планируется ли подобная встреча в Питере?
Уточните, пожалуйста, на чем основана рекомендация передавать аргументы string_view по значению? Из соображений производительности следует, что передача по ссылке займет на стеке 1 указатель, а по значению 2 (буфер и длина).
Передать два слова дешевле, чем устраивать лишнюю индиректность. Читать статьи про устройство современных процессоров, Bust Mode и прочее…