Комментарии 260
И когда им научатся компиляторы отличные от MSVC? (многие фичи начинают поддерживаться раньше выхода стандарта, а тут никто кроме MSVC не торопится)
Это то я знаю. Но войдёт ли в C++20 или надо ждать ещё дольше?Этого вам никто не скажет до выхода стандарта. Истории с
std::async
хватило.И когда им научатся компиляторы отличные от MSVC? (многие фичи начинают поддерживаться раньше выхода стандарта, а тут никто кроме MSVC не торопится)Вот именно в этом — и проблема: на платформах, отличных от Windows, это никому не интересно (по разным причинам). А Windows-only технологию вряд ли удастся пропихнуть в стандарт.
С другой стороны альтернативное предложение (которое мне лично нравится гораздо больше) вроде как заглохло, так что может быть и примут… но не факт, что в C++20.
Можете либо уточнить, что имели в виду, а ещё лучше, предоставить сслыку, если там какой-то разбор фатального недостатка, пожалуйста?
Или всё довольно банально и `std::async` просто откладывался несколько раз?
Можете либо уточнить, что имели в виду, а ещё лучше, предоставить сслыку, если там какой-то разбор фатального недостатка, пожалуйста?Вот тут есть большая статья с дополнительными ссылками.
Или всё довольно банально и `std::async` просто откладывался несколько раз?Наоборот — его «по-быстрому» включили в стандарт… теперь расхлёбывают…
Если коротко, то оказалось что
std::async
в том виде, в каком он стандартизован использовать практически невозможно — хотя можно использовать вариации реально реализованные разными вендорами опираясь на вещи не описанные в стандарте.Когда Microsoft выкатил своё предложение, то оказалась, что там — та же фигня: реализация ровно того, что они предложили не позволяет писать работающие программы, а то, что реально реализовано в MSVC — опирается на некоторые вещи, которые в стандарте не упоминаются.
Кому и зачем такой стандарт нужен? C++ — это ж не OOXML, который был нужен Microsoft'у, чтобы продавать офис в некоторых странах, расширения, которые нельзя использовать без учёта специфики конкретной реализации, вполне себе могут жить и вне стандартарте без формального «окропления водой» комитетом по стандартизации.
Посему было решено подождать пока будет ещё хотя бы одна реализация… но только оказалось, что это никому, кроме Microsoft'а не интересно — а в таком случае… зачем спешить?
В язык обычно что-то добавляют. Удаляют очень и очень редко. В комитете стараются тщательно следить за обратной совместимостью.
А вот потрындеть о состоянии языка на собеседовании — милое дело. Сразу видно, что у человека болит и, соответственно, чем он на самом деле плотно пользовался.
Кстати, почему обычное статическое поле вы называете синглтоном?
T &instance() {
static T instance;
return instance;
}
Он пишется меньшим количеством кода и сам заботится о потокобезопасности.
А уж квантовые переменные с «Редукцией фон Неймана» — это вообще непонятно куда отнести. Вроде как сахар, а реально — на этом можно такие вещи построить, которые без них вообще фиг сделаешь. С Boost.Hana поиграйтесь — очень весело…
Я с ханой не сильно много игрался, но довольно много чего делал сам, и там variable templates экономили максимум что пару скобочек, фигурных али круглых.Вы с variadic templates не путаете? Попробуйте без них написать функцию, которая принимает произвольный список типов и для каждого типа — свой обработчик.
Вот что-то подобное:
#include <boost/hana.hpp>
#include <boost/hana/ext/std/tuple.hpp>
namespace hana = boost::hana;
auto handlers = hana::make_map(
hana::make_pair(hana::type_c<int>,
[](int i){ printf("0x%04x\n", i);}),
hana::make_pair(hana::type_c<double>,
[](double g){printf("%10.2g\n", g);})
);
template<typename Tuple, typename Handlers>
void handle(Tuple tuple, Handlers handlers) {
hana::for_each(tuple, [handlers](auto o){
handlers[hana::type_c<decltype(o)>](o);
});
}
int main() {
auto tuple = std::make_tuple(1, 2.0);
handle(tuple, handlers);
}
Вы про hana::type_c<int>?Я про то, что вы можете передать
hana::type_c<int>
туда, куда нужно передавать переменную. В частности — можете сопоставить тип и что-то вычисляемое (массив какой-нибудь).Ну напишу вместо этого hana::type<int> {}, проблем-то.Проблемы таки возникнут. Потому что: The actual representation of hana::type is implementation-defined. In particular, hana::type may be a dependent type, so one should not attempt to do pattern matching on it.
У каждой variable template есть тип, и в неэзотерическом коде он вряд ли будет невыговариваемым.Вопрос не в «выговариваемости». Вопрос, как я уже сказал, в «корпускулярно-волновом дуализме». Variable template — это всё-таки variable. Она одна (пусть и неизвестно какой у неё тип). Её можно менять как угодно, передавать куда угодно и вообще — работать с ней как с переменной.
hana::type<int> {}
же — это один из обьектов с определёнными свойствами. Что очень и очень усложняет работу с ними.P.S. Так-то вообще всё, что вы делаете можно в brainfuck отобразить. И сказать, что ни в одном языке программирования ничего, кроме «сахара» для brainfuck'а-то и нету.
А на собеседовании всё равно спростя про стоимость виртуального вызова и что такое виртуальное наследование. На это всё закончится.
auto operator<=>(const point3d&) const = default;
зачем такая ужасная конструкция в языке? а default = const будет работать?
auto operator<=>(const point3d&) const = default;
Кроме того, можно писать тело самого оператора, если вам необходимо какое-то особое поведение:
#include <compare> // weak_ordering, is_neq
struct point3d {
int x;
int y;
int z;
std::weak_ordering operator<=>(const point3d& p) const {
using std::abs;
if (auto cmp = abs(z) <=> abs(p.z); std::is_neq(cmp)) return cmp;
if (auto cmp = abs(x) <=> abs(p.x); std::is_neq(cmp)) return cmp;
return abs(x) <=> abs(p.x);
}
};
В вашем 'особом' поведении закралась бага.
antoshkka лучше скажи, когда откроете сорцы libgeobase, я бы переписал на Rust.
И только в IT считается, что двухмесячных курсов должно быть достаточно для того, чтобы претендовать на зарплату, которая будет выше, чем у начинающего архитектора или терапевта.
В IT все меняется с каждым годом все быстрее. Поэтому пора изобретать принципиально новые подходы к программированию и его обучению. Да, за 2 месяца С++ не выучить, но зато можно выучить другой какой-то язык. Мне кажется, не за горами тот год, когда мы начнем писать программы на своем естественном языке с нормальным уровнем абстракции без этих spaceship default const.
И бац! С++20. Опять надо учить, опять ты никому не нужен.
Чай, не джаваскрипт) Вряд ли кому-то откажет работодатель по причине того, что кандидат не в совершенстве освоил новый стандарт. Тем более, что первые пару лет еще придется поискать конторы, которые начнут его применять.
Как тут уже верно замечали, действительно концептуальное изменение было одно — семантика перемещения в C++11 (спустя 7 лет от предыдущего стандарта), всё остальное — сахар, который усваивается прямо по ходу дела.
> Кол-во разработчиков увеличивается вдвое каждые 5 лет. Соответственно половина разработчиков ПО имеют < 5 лет опыта в бою.
Еще в другой речи о будущем программирования он освещает тему важности качественно написанного кода. От некоторых программ зависят жизни миллионов человек. И 20 лет опыта вполне нормальная цифра при такой ответственности.
Спасибо, что подогрели мой интерес :)
Никто не мешает Вам как разработчику на С++ использовать только какое-то подмножество языка и не изучать все его тонкости и дебри. Это совершенно ни к чему.
Рассматривается потихоньку пропозал насчёт графики.
Никто не мешает Вам как разработчику на С++ использовать только какое-то подмножество языка и не изучать все его тонкости и дебри. Это совершенно ни к чему.
1. Подходит на 100% в случае разработки приложения в одиночку с использованием только стандартной библиотеки.
2. В команде уже начинаются сложности, но в целом их можно преодолеть разработав собственные инструкции, которых все должны строго придерживаться. Но это уже потенциальная проблема от простого недовольства до принципиального отказа работать в команде.
3. Но как насчёт сторонних библиотек? Как заставить их авторов придерживаться ваших правил?
Поэтому на мой взгляд просто взять и проигнорировать всё, что не нравится или непонятно, при работе в команде над серьёзным приложением не получится.
Я бы добавил возможности связанные с графикой, что бы начинающим (и не только) стало легче и интереснее работать с этим языкомВы хотите сказать «сложнее и попобольнее», как я понял.
Я не видел ни одной библиотеки для работы с графикой, ни на одном языке программирования, которая была бы уместна и в программе на iOS и в программе для Windows и в программе под Android. Есть всякие кроссплатформенные вещи (типа той же Ауры), но опять-таки — игры на них делать не будешь.
Пока что почти вся стандартная библиотека C++ устроена так, что её можно использовать в любом проекте под любую платформу. Графические вещи с этим же свойством — я представить себе не могу.
P.S. Речь не идёт о том используются они или нет. Если проект достаточно старый — там и строки могут быть QT'шные (или свои собственные) и callback'и и прочее. Но в новом проекте — вполне можно использовать то, что входит в стандарт. И люди регулярно отказываются от своих «велосипедов». Представить себе графическую библиотеку с подобным свойством, я, увы, не могу.
Нет, я не спорю: QString — хорошая вещь… для того времени, когда она была написана… Но сегодня… лучше иметь библиотеку поверх std::string. Эх, если б только разработчики ICU не страдали фигнёй…
правда сам писал)
Иксы до сих пор не особо многопоточные, отрисовывать всё равно только из одного треда можно.И именно поэтому COW — глупое решение. Читаем. Черно-зелёным написано: Qt, however, uses atomic reference counting to ensure the integrity of the shared data, avoiding potential corruption of the reference counter.
Вы знаете сколько стоят атомики на современных многоядерных CPU?
Да и вообще в GUI-коде, вероятно, удобство API куда важнее производительности строк.Ага. А в других местах — давайте использовать другие строки. Как Windows — разведём зоопарк и будем в них путаться потом.
Вы же не перелопачиваете гигабайты данных прям в гуях?Не перелопачиваю. И тем страннее выглядит решение получить копеешную экономию памяти (да и то не факт: на практике за счёт того, что std::string для коротких строк память не выделяет потребление памяти может оказаться меньше, чем с QString'ами) за счёт существенного замедления простых операций.
В принципе, есть ещё всякие boost.format, boost.algorithms, и так далее, но почему-то эту часть буста я патологически не переношу.Там тоже много странного, да. Сделать хорошие строки — весьма непросто, как показывает практики. Во всех языках и библиотеках — с ними те или иные проблемы.
std::string
с utf8
содержимым — не самый худший вариант, а с учётом того, что это, фактически, стандарт — стараюсь им и пользоваться.Что там в STL работает на платформах без поддержки исключений, пара алгоритмов, std::is_* да std::array?
Поищите замечательные доклады от SG14 (game dev, low latency). Они пытаются уйти от исключений в сторону более быстрых механизмов сообщений об ошибках… И не могут найти механизмы, которые работали бы быстрее, в случае отсутствия ошибки.
Читайте современные исследования, не используйте исключения для «не ошибок» и всё будет хорошо.
Ну вот в том же Rust-е есть Cargo, которая снимает изрядную часть головной боли с растоманов. В C++ же все, такое ощущение, осталось неизменным с середины 80-х годов. Каждый волен извращаться как хочет. В итоге систем сборки как грязи, на любой вкус, что особенно доставляет, когда в одном проекте нужно объединить библиотеки, использующие разные системы.
Понятное дело, что стандарт C++ — он совершенно не про то, и в стандарте не будет прописываться какая-то система сборки. Но хотя бы эта проблема затрагивается в кулуарах?
Вы их прямо в дерево проекта добавляете и дёргаете их сборку из вашего мейкфайла/CMakeLists.txt/.jam?А как надо? Чтобы просто, кроссплатформенно, повторяемо?
Ну и да, не весь мир пользуется CMake.А почему, собственно?
И не желает, что характерно.Ах, вон оно чё, Михалыч. Ну дык а почему весь мир вдруг возжелает пользоваться новыми тулзами, которые комитет разработает?
Думаете перейдут потому, что это стандарт? Тогда об этом смысла нет говорить без работающих модулей. Ибо переход на C++11 до сих пор не завершен — а ему, как бы, уже довольно много лет. То есть даже в самом оптимистичном случае распространение эта система получит уже в эпоху, когда C++'никам будет что ответить на вопрос: «почем в Tubro Pascal'е модули появились 30 лет назад, а в C++ их нет до сих пор». Без модулей в любой системе будет очень много времени и сил уходитm на обслуживание костылей, их заменяющих, а если скоро — системы управления зависимостями не будет, тогда зачем в ней всё это?
Ибо складывается ощущение, что C++-комьюнити само выбирает тот же CMake и ничего хорошего в этом нет :(
Плюс есть такой фактор, что когда люди говорят про модули, которые ожидаются в C++, то у многих складывается ощущение, что с пришествием модулей наступит такое же благоденствие, как в каких-нибудь языках с поддержкой модулей, вроде D или Rust-а, где сам компилятор может разобраться в каком порядке что компилировать. С большой долей вероятности в C++ это будет не так. Если только коммитет на озадачиться тем, чтобы у языка была своя де-юре стандартная система сборки.
При появлении де-юре (да и даже де-факто, но признанного большинством) инструмента для управления зависимостями, процесс адаптации под него обязательно пойдет. Какая-то часть старого кода, естественно, никуда не денется. Но вот новый код будут делать уже с расчетом на него.
Тоже самое и системами сборки. Вот становится CMake де-факто стандартом и те проекты, которые развиваются, волей-неволей, но вынуждены либо переходить на CMake, либо добавлять какую-то поддержку для него (например, FindFoo.cmake-файлы).
std::is_pod и std::is_pod_v помечены как deprecated.Можно поподробнее?
bool is_pod()
{
return is_standard_layout<T>::value && is_trivally_copyable<T>::value;
}
Какая-то сомнительная мотивация, хотя в type_traits это не единственная странность, взять к примеру наличие is_member_function_pointer, но отсутствие is_function_pointer.
То есть мотивировать людей писать локальную функцию?А зачем вам эта функция? Если вы хотите засунуть это в
realloc
, то вам нужно is_trivally_copyable
, если вам нужно с C общаться — вам нужен is_standard_layout
, а вот случаи, когда нужно и то и другое — крайне редки (да собственно уже и is_trivally_copyable
мало когда нужен, а уж чтобы был нужен POD и именно POD — я ни разу не встречал, хотя чисто теоретически такое можно придумать, но… не встречал).Взять к примеру наличиеТа же самая ситуация: в 99% случаев вместо гипотетическогоis_member_function_pointer
, но отсутствиеis_function_pointer
.
is_function_pointer
— нужно использовать is_invocable
. А если очень нужно (зачем?) — то можно, наверное, и самому такое изготовить…Для is_invocable нужен список аргументов, и добавили его только в С++17, а не в С++11 как остальные две функции. Вопрос «зачем» здесь вообще не актуален, если есть библиотека для поддержки информации о типах, то там должно быть все, что с этим связано. С таким же успехом можно спросить «Зачем нужна is_arithmetic, если это всего лишь is_integral && is_floating_point?».
С таким же успехом можно спросить «Зачем нужна is_arithmetic, если это всего лишь is_integral && is_floating_point?».Можно. И можно получить разумный ответ: есть вещи в стандарте, которые разрешены только для арифметических типов и запрещены — для всех остальных. А вот для POD — таких мест нет.
Мне запись is_pod кажется гораздо более очевидной, чем is_standard_layout, как и само определение «plain-old-data» проще осознать, чем «standard layout».И именно поэтому сотни и тысячи програмистов используют
is_pod
там, где нужен is_standard_layout
.Рассмотрим простой пример. Вот такой тип:
struct Test {
int x = 0;
int y = 0;
int z = 0;
};
Ну надоела мне вечная возня с неинициализированными данными. Могу я его передать в C? Да, разумеется — это standard layout класс. Могу я использовать его с вашей библиотекой? Да господь с вами: вам же is_pod
писать удобнее, а что кто-то там безопасности и предсказуемости хочет — так это его проблемы.Нафиг-нафиг-нафиг. Если что-то слишком легко использовать неправильно — то лучше это что-то из языка и/или библиотеки удалить.
auto_ptr
и is_pod
— как раз такие вещи. Вы, собственно, так и не ответили на вопрос: где вы is_pod
применяете и почему вам is_standard_layout
не подходит. А без этого дальнейшие рассуждения как бы бессмысленны.constexpr
выражений (включая конструкторы и деструкторы!), default member initializers и прочего оказалось что слишком часто использование is_pod
«не по делу» мешает писать красивый и удобный код.Да, можно выкрутится, скажем сделать POD-класс предком того класса, с которым вы, в большинстве случаев, работаете, но это всё — костыли, которые грозят слезьми при малейшей ошибке. Гораздо лучше — использовать ровно то свойство, которое вам нужно. В C++17 POD'ы упоминаются буквально в паре мест — и, есть подозрение, что в C++ не будут упоминаться вообще нигде. Тем самым понятие потеряет всякий смысл с точки зрения языка.
P.S. Кстати класс из моего примера и
is_standard_layout
и is_trivially_copyable
. Он не POD — потому что он не is_trivially_default_constructible
— что тоже бывает нужно (например только такие типы вы можете считать «готовыми к употреблению с помощью reinterpret_cast
а поверх абстрактного куска памяти, выделенного malloc
ом) — но очень редко.Я вот сижу на Delphi, как не посмотрю в сторону C++, нет почти подвижек, модули все только обещают, о рефлексии разговора толком нет, как вообще можно жить без рефлексии? Про строки которых 100500 у каждой либы и все не совместимы, я молчу(ок так исторически вышло).
Зато графика, комплексные числа — в стандарте — ага, спасибо.
о рефлексии разговора толком нет, как вообще можно жить без рефлексии?А чего именно вы хотите от рефлексии? А то как-то я спокойно без неё живу с type_traits… чего я такого важного теряю?
P.S. Сразу предупреждаю, что инспекторы объектов я не пишу, но пользую — они отлично работают с DWARF'ом и поддержки в стандерте, как бы, не особо и требуют… всё равно для них требуется куча вещей, которых в стандарте нет… интересует куда и какую рефлексию аж такую, что без неё «жить нельзя» хотите приспособить… После получения реальных примеров уже можно будет и о расширении языка говорить…
реальнее того что Qt работает исключительно чрез эмуляцию Reflection.Gtkmm работает без «эмуляции Reflection», Aura работает без «эмуляции Reflection», да и старый добрый WTL как-то без этого обходится.
Хочешь рефлексию — прикручивай костыли, сейчас, когда почти все языки поддерживают эту базовую функцию — даже не смешно говорить о необходимости.Тысячи леммингов не могут ошибаться? А поконкретнее чего-нибудь можно?
То, что Qt'шники хотят делать в рантайм вещи, которые на C++ сделать можно только в compile-time не значит что нужно прям всё бросать и превращать C++ в Java: есть сотни проектов и тысячи библиотек, которые без этого как-то живут. А для тех, кто хочет Java, вы не поверите, есть Java.
Так что вопрос остаётся в силе: какую-такую рефлексию без которой «жить нельзя» вам нужно — и для решения какой бизнес-задачи вы хотите её приспособить? А также — и это очень важно — сколько будет «стоить» ваша рефлексия если вы её не будете использовать?
В любом случае это во много раз нужнее ограниченой графической либы.Возможно. Но на графическую либу смотрят совсем не те люди, которые могли бы что-то сделать с рефлексией в любом случае.
То, что в C++ вообще есть RTTI, как мне кажется, есть ошибка (это одна из немногих фич, которая чего-то ощутимого стоит, когда ею не пользуются — недаром в большинстве компиляторов есть флаг -fno-rtti или что-нибудь подобное — а ведь «selling point» C++ состоит как раз в том, что ты не платишь за то, что не используешь), не стоит её усугублять.
Плюс, есть ещё всякие Q_INVOKABLE и Q_PROPERTY, которые торчат наружу в QML и прочие скриптовые вещи.Они, к сожалению, просто «торчат наружу», а не «торчат наружу в QML». У вас нет никакой возможности узнать — используются они или нет.
С точки зрения языка это — просто некоторое описание данных для внешнего потребителя.
В Gtkmm/WTL есть аналог QML?Нет, разумеется. Это будет противоречить самому принципу: программа должна быть доступна компилятору C++.
Как выдать данные дня «внешних потребителей» — над этим сейчас очень серьёзно работают. Но поскольку тут уже «играют» не только потребности C++-программистов, то очень тяжело понять, прежде всего — что, на самом-то деле нужно и что, без существенных изменений языка, возможно.
Когда мне в качестве примера говорят: а возьми, мил-человек, 50MB+ исходничков и перелопать из начала в конец и из конца в начало — а потом уж разговоры разговаривай… это неконструктивно. Вот это -уже конструктивнее. И SG7, разумеется, этот блог-пост читал…
Зачем мне об этом узнавать?Затем что иначе нарушается базовый принцип C++: платите только за то, что используете.
Что значит, что подход, принятый в Java или Qt для C++, в общем, недопустим: нужны не метаклассы как таковые, а инструменты для их создания.
Если в рантайме, то это прикручивается, если в компилтайме, то для динамических вещей вроде QML или Python-скриптов это не особо возможно.Что, собственно, и обозначает, что требуется помощь со стороны программиста — только он может сказать какое, когда и в каких количествах знание нужно экспортировать из C++ программы.
Только я бы голосовал за компил-тайм-рефлексию. Рантайм-рефлексия через неё выражается, а в обратную сторону оно не работает.Это само собой — но это сразу же ставит кучу вопросов, которые достаточно сложно решать. Очень мало языков имеют компайл-тайм рефлексию не имея рантайм рефлексии. C++ здесь, во многом, первопроходец.
Безотносительно принципов, на QML всякие свистелки-перделки очень кратко и ёмко выражаются, и для некоторых сортов интерфейсов и задач это самое оно.Возможно. Но на C++ — свет клином не сошёлся и, возможно, для решения каких-то задач стоит использовать другой язык. Я вот не уверен, что «свистелки-перделки» использующие в 10-100 раз больше ресурсов, чем, на самом деле, нужно — это вообще то, что нужно делать на C++.
Эм, а чьи ещё? Мы ж о С++ говорим.Нет. Когда мы начинаем рассуждать о DBus, QML и прочем — то это значит, что у нас появляются какие-то жёстко заданные требования «извне», которые в языке C++ не определяются.
Такие вещи в C++ есть (начиная с
extern "C"
, ага), но говорить о них всегда сложнее, так как эсперты по этим «внешним» вещам считают очевидным, что все понимают — что им нужно, что, как бы, ни разу не так для людей, которые соответствующую технологию не используют.Ну, эти юзкейсы должны быть чем-то вроде граничных условий, позволяющих проверить, является ли данное предложение о рефлексии разумным, позволяет ли оно выразить те юкзейсы, или нет.Ну дык об этом и речь! Отсюда, собственно, и нужно «танцевать». А не с заявлений: нужна именно внтуриязыковая по типу в C# или Java. Если вам нужен C# или Java, то, чёрт побери, кто вам запрещает использовать C# или Java? Они проде есть и умирать (к сожалению или к счастью — не знаю) пока не собираются…
Вот это -уже конструктивнее. И SG7, разумеется, этот блог-пост читал…
Предложение Герба Саттера по метаклассам всё-таки попроще будет
Хорошо, что благодаря Qt эти вопросы решаются и сильно расширяют возможности C++.
IDE Visual Studio написана на .NET (WPF), и она совершенно не тормозит.
IDE Idea, Rider написаны на Java, и они тоже не тормозят.
1) Напиши таблицу в C++/Qt Excel на тысячи строк и пару десятков столбцов — она не будет тормозить. И в C#/Java хотя бы пару сотен строк (лаги видные невооружённым взглядом) и сравни.
2) IDE Visual Studio — посмеялся. Сравни с 2008 студией, когда там WPF ещё не было
3) IDE Idea — пользуюсь каждый день, но сравнивать с реактивным Qt Creator смешно особенно запуск (в идее — около минуты, креатор — несколько секунд), загрузку проекта, скроллинг и навигацию.
2) Сейчас подходит к концу 2017 год.
3) Ну так и пользуйтесь Qt Creator-ом. Всё дело в функционале же.
Да, чтобы работало быстро, придётся ручками писать код.… на C++
Ну так и пользуйтесь Qt Creator-ом. Всё дело в функционале же.Дело не в креаторе или IDEA — пользуемся тем, что нужно для задачи. А в том, что с рефлексией уровень задач решаемых C++ значительно бы вырос.
А в том, что с рефлексией уровень задач решаемых C++ значительно бы вырос.Совершенно необязательно. На примера Java я вижу, что рефлексию, как правило, используют для того, чтобы сделать код «гибчее» и… медленнее и прожорливее!
Я не уверен, что это прям то, что так уж нужно С++. Но да, в определённых случаях во всём этом есть смысл.
… на C++
Это не важно, даже при использовании C# основное процессорное время будет затрачено в user32.dll и gdi32.dll.
Хотите, чтобы я привёл пример?
Просто наличие удобных инструментов расслабляет программиста, и он не думает о производительности. Да и скорость разработки сейчас — это более важный фактор, чем производительность софта.
Это не важно, даже при использовании C# основное процессорное время будет затрачено в user32.dll и gdi32.dll.Почему Qt не затрачивает это процессорное время? Обычная программа на C#/Java работает раза в 2 медленнее, а GUI на порядок медленнее, чем C++/Qt.
Обычная программа на C#/Java работает раза в 2 медленнее
Да, работает медленее. И что? Просто не пишите UI, требующий большого количества вычислений.
а GUI на порядок медленнее, чем C++/Qt.
А QtSharp?
И вообще, как GUI может работать медленнее, если он просто сводится в вызову системных функций?
И да, здесь многоуровневые слои рефлексии и фабрики-фабрик-фабрик ни разу не помогают.
Да, работает медленее. И что? Просто не пишите UI, требующий большого количества вычислений.
Тут вопрос стоит так: «справляется или не справляется GUI-поток?». Справляется? — всё хорошо. Не справляется? — плохая программа, тормозит и виснет. А реальная разница в быстродействии может быть и в не вдвое, а процентов на 20
И вообще, как GUI может работать медленнее, если он просто сводится в вызову системных функций?
потому что Qt использует не нативные виджеты, а собственную реализацию, которая выглядит как нативные виджеты.
Да и скорость разработки сейчас — это более важный фактор, чем производительность софта.
Итоговая программа всё равно должна удовлетворять требованиям, в т.ч. и по отзывчивости/быстродействию. Не сказал бы, что на с++/Qt программы пишутся прям намного дольше, чем на шарпике. Для некоторых приложений возможно даже, что и быстрее, т.к. меньше времени уйдет на оптимизацию бизнес-логики.
IDE Visual Studio написана на .NET (WPF), и она совершенно не тормозит.Ага. Щаз. Запустите из на Atrom'е на 1GHz и сравините с Visual Studio 6.0 (последняя, не испорченная C#).
IDE Idea, Rider написаны на Java, и они тоже не тормозят.
И современная Visual Studio и Idea и Rider — тормозят безбожно. Конечно сделать их тормозами не было основной задачей и за то, что системные ресурсы и потребная мощность процессора возросли на два порядка мы таки кое-что получаем, но… контрпримерами они не являются ни разу, увы.
сравините с Visual Studio 6.0 (последняя, не испорченная C#).
Сравнение, мягко говоря, не особо эквивалентных программ по функционалу.
То, что Visual Studio 6.0 «не умеет» IntelliSense — да, правда, но тормозит-то в Visual Studio 2017 не только IntelliSense, а вообще всё!
Тем не менее, для использования современной студии не нужно «особое» оборудование, достаточно обычного офисного компьютера. Она с открытым проектом среднего размера будет потреблять памяти столько же, сколько Firefox с единственной вкладкой Хабра.
модель кода и всякие рефакторинги-интеллисенсы в CLion лучше, но это не повод тормозитьДе нет — в общем-то повод (пока никто не сделал быстрого интерфейса с хорошим интеллисенсом, так что ясно, что это непросто), но… это хороший тест: если человек заявляет, что CLion, Idea, MSVC, или, не дай бог, Eclipse «не тормозят» — это значит либо, что у него плохое зрение, либо что у него очень, очень дорогой и быстрый компьютер — а часто и то и другое одновременно.
Вы правы. Не вижу никакого смысла использовать Atom для
разработки. Ведь компьютер — это основной инструмент, а на инструментах экономить нельзя.
Ну и важный момент — мои проекты не очень большие (~500 файлов, 3М текста), а студию я использую голую, т.к. с плагинами (Resharper, VAssist) она действительно тормозит.
Хорошо, что благодаря Qt эти вопросы решаются и сильно расширяют возможности C++.Так они «решаются» или «если бы в C++ была рефлексия — язык рванул бы»?
Вы уж выберите что-то одно, а?
Это уже разговор ни о чём пошёл.Я понимаю, что для верующих обсуждать вопрос их веры бессмысленно, но вроде как пока что «школы адептов рефлексии» не наблюдается, так что вопросы нужно обсуждать по-существу, а не в духе «примите нашу веру — и будет вам ЩАСТЯ».
Так что у вас получается, что языку не хватает средств для общения с другими библиотеками и языками, но при этом мы ничего в проект тащить не хотим.
Вы уж определитесь — вам шашечки или ехать.
А тогда непонятно, чем вам рефлексия в языке поможет. «Внутриязыковая» рефлексия в C++ уже и так достаточно развита.Это какая, например?
То, что нужно — это «внеязыковая» рефлексия позволяющая как-то общаться с библиотеками и скриптами не написанными на C++.Ничего подобного не требовалось. Нужна именно внтуриязыковая по типу в C# или Java.
Слышали про Template Haskell что-нибудь?Слышал, слышал. Про то, как вызывать его из Java или C++ библиотеки — не слышал.
В мире С++ я бы хотел написать один раз один метакласс, который потом мне сгенерит DBus-обёртки для моего типа.Ну то есть опять — что-то для внешнего потребителя. Который не существует на этапе компиляции программы. Тут сразу встаёт задача классификации этих потребителей и их «хотелок». Так как они «живут» вне C++ кода, то про них и их «желания»/«ограничения» мы знаем очень мало. И пока не будем знать достаточно — хорошего решения не придумаем.
Или будет проксировать вызовы методов через какой-нибудь [другой] RPC-механизм.Опять-таки: чего вы от него хотите.
Или сгенерирует методы для сериализации-десериализации.Magic Get делает это в рамках C++14.
Или для работы с представлением типа в БД.А тут — снова возникает вопрос: что конкретно и зачем.
То есть так-то понятно, что рефлексия — это хорошо… но вот что именно нужно и насколько оно востребовано… дьявол, как обычно, в деталях. C++ — всё-таки компилируемый язык… Мне очень нравится Beautiful Soup — но я понимаю что подобные трюки в C++ не сработают если мы захотим в «жёсткую структуру» всё загнать: на этапе компиляции мы ж не знаем какие теги возможны и какие в них могут быть субтеги! А если всё делать гибко поверх std::any — ну так там и рефлексия сразу в таком дереве будет!
И ни для чего из этого не нужно прямой поддержки в ядре языка, всё это библиотечный код, в ядре языка достаточно просто уметь управляться с AST.Этим путём идёт rust… посмотрим что из этого выйдет.
Конечно, вы правы — она это уже делает, но есть чувство, что через правильную рефлексию оно всё будет выглядеть куда лучше.А в этом, собственно, и проблема: поскольку через костыли это делается уже сейчас — то никому неинтересно добавлять «какую-нибудь» рефлексию. «Какая-нибудь» уже есть (и не одна, да).
Это как сравнивать SFINAE-костыли и полноценные концепты.Не обязательно SFINAE. DWARF — это тоже рефлексия и тоже стандарт, хотя и не ISO C++.
В том-то и дело, что уже много чего есть и вопли «адептов рефлексии» — это «пена», на которую не стоит обращать много внимания.
Да, рефлексия нужна. Но она не нужна «вот прям щаз» («костыльных» решений — вагон и маленькая тележка) — лучше подумать и сделать хорошо. Над этим — работают, хотя и медленно.
Я обожаю чистый C, и спокойно обхожусь без строк, но их отсутствие заставляет меня выбрать другой язык для некоторых задач, где отлично бы подошел C, были бы в нем строки.
Также и тут, это сильно ограничивает возможности C++, хотя-бы отсутствием возможности сделать автоматическую сериализацию. И да, я видел несколько попыток сделать это макросами и набором костылей — это плохой способ, в котором разбирается только автор.
И да, я видел несколько попыток сделать это макросами и набором костылей — это плохой способ, в котором разбирается только автор.Кто вам сказал, что сериализация, которую напишут поверх рефлексии будет лучше?
Это тогда уж нужно добавлять библиотеку сериализации в стандарт — а это совсем-совсем другая история. Её, как бы, можно сделать уже сейчас через magic_get, но… не делают. Пользуют всякие протобуфы, Cap’n Proto или даже JSON'ы.
Хочется увидеть примеры, которые были бы осмысленны в рамках C++. «Эмуляция рефлексии» в Qt к подобным примерам отнесена быть не может: как уже верно заметили Qt был сделан именно так, потому что хотелось поддерживать «весьма унылые компиляторы». Другие современные библиотеки спокойно существуют без рефлексии.
Сериализация через рефлексию — это круто и здорово… только вот в Java, где вроде как рефлексия и есть и сериализация через неё есть RPC делают не через сериализацию поверх рефлексии, а через JSON, XML и многое другое. А рефлексию используют для того, чтобы сделать программы «гибчее»… и тормознее. А последнее — это уже совсем не C++-way.
Пока что единственный заслуживающий внимания пример — это генерация Dbus-биндингов. Тут — действительно рефлексия нужна и в том виде, в каком она есть недостаточна.
Все же остальные примеры — скорее о том, как с помощью рефлексии что-то сделать плохо (медленно, небезопасно и с затратой кучи памяти). Вряд ли желание кого-то что-то делать «быстро и плохо» — может являться причиной для добавления новой фичи в язык. Языков, на которых получить более быструю разработку за счёт качества получаемого продукта — достаточно много и без C++.
Приведите хоть один убедительный пример зачем в C++ есть шаблоны?
Много проектов, которые генерируют код сторонними скриптами, есть 101 способ обойтись без шаблонов. Шаблоны лишь затрудняют чтение кода. Зачем они нужны не ясно.
</сарказм>
Так вот, даже если в других языках это принято делать рефлексией, в C++ большинство этих задач можно решить без неё. В некоторых случаях рефлексия таки могла бы быть удобной (Dbus биндинги например). Но а) рефлексия не очень ложится на общую структуру и цели C++, б) Если уж очень надо — действительно есть костыль в виде той же кодогенерации внешними скриптами. Если сообщество придумает способ органично вписать рефлексию или что-то её заменяющее — наверняка это примут в стандарт. А пока — имеем то, что имеем. В конце концов есть другие языки, если C++ для конкретных задач не нравится использовать.
<сарказм>Уберите теги "</сарказм>", пожалуйста.
Приведите хоть один убедительный пример зачем в C++ есть шаблоны?
Много проектов, которые генерируют код сторонними скриптами, есть 101 способ обойтись без шаблонов. Шаблоны лишь затрудняют чтение кода. Зачем они нужны не ясно.
</сарказм>
Потому что ваши слова правильны и справедливы. Как же так: как я, фанат таких вещей, как Boost.Hana или любитель что-нибудь этакое сотворить через шаблоны могу так говорить?
А вот так. Шаблоны, в том виде, в котором они изначально были задуманы — практически никому не нужны. Я не могу вспомнить ни одного проекта, в котором я бы использовал basic_string, но не std::string, а всякие mapы — вполне могли бы существовать в виде Ada-стайл genericов.
А шаблоны… шаблоны — нет, не нужны. Что было нужно (и сейчас нужно!) — так это средства метапрограммирования. Однако их — в С++ не было. А шаблоны — были. И вот, когда Степанов придумал как с помощью шаблонов можно сделать плохое, кривое, но… всё-таки, работающее метапрограммирование — язык C++ стал чем-то большим.
Однако то, что метапрограммирование в нём — плохое и неудобное, а шаблоны по-прежнему не нужны — накладывает особый отпечаток на программистов на C++. Они плавают на перевёрнутом «вверх ногами» Боинге, а тот факт, что для этого нужно тщательно следить, чтобы ни через один иллюминатор не просочилась вода — считают достоинством и объясняют новичкам, что «так и надо».
Нет — так, не надо. Надо бы — корабль использовать. Но… корабля у нас нет, а вот этот самый Боинг с рядами гребцов — у нас есть. Но раз мы плаваем на Боинге, то и некоторые решения у нас оказываются… специфические. И вовсе не факт, что прикрутив на этот Боинг гребной винт мы получим облегчение: совершенно не факт, что эта конструкция будет лучше плавать — уж очень она отличается от той, для которой предлагаемый винт изначально предлагался…
И вот, когда Степанов придумал как с помощью шаблонов можно сделать плохое, кривое, но… всё-таки, работающее метапрограммирование — язык C++ стал чем-то большим.Это когда это Степанов придумал метапрограммирование на шаблонах? Степанов реализовал на шаблонах C++ свои идеи по обобщенному программированию, которые у него были еще с начала 1980-х. А метапрограммирование на шаблонах — это, как минимум, 1995-й год, когда STL уже был и его включали в первый стандарт C++.
Но остального — это не меняет: шаблоны в современном C++ используются почти исключительно «не по назначению», все связанные с ними проблемы (бинарники в
Я думаю в альтернативном мире, где не было бы частичной специализации (то есть там, где шаблоны были бы дженериками), и где в C++ пришлось бы добавлять и нормальную рефлексию и нормальное метапрограммирование — всё было бы по-другому и, скорее всего, лучше и удобнее… но мы не живём в этом мире, увы… и попытки скрестить то, что есть с тем, что, как бы, хочется способны родить тааакого урода, что использовать его не захочется никому и ни для чего…
Людям то «виднее». Им подавай «как в ***», где *** — каждый второй ЯП. Им надо «чтобы просто вот такой код генерировался с набором параметров». Люди хотят еще один препроцессор…
Вспоминается анекдот: «невозможно понять, чего хочет женщина: сам бог дал ей брови, но она их сбрила и нарисовала карандашиком».
Разве что с T&& в шаблонах реально бред вышел
Если бы компилирование было двухэтапое: сначала в VM, затем в нативный код, то это было бы просто. Например, существует множество совметимых друг с другом языков, которые компилируют в MSIL или JVM.
А была бы нормальная работа с AST, включая Oxford brackets, можно было бы сделать, скажем, библиотечную интерполяцию строк.«Нормальная работа с AST» — это, как бы, уже далеко не возможность отслеживать и модифицировать собственную структуру и поведение во время выполнения. Это возможность формировать новые обьекты во время компиляции — о чём пока и близко речи не идёт.
Тут уже начинается софистика: может ли быть в компилируемом языке рефлексия вообще или нет.
Принципиальная позиция Страуструпа (с момента создания языка) — в обьектный код классы, шаблоны и прочее не попадают. Попадает некая «выжимка», необходимая и достаточная для того, чтобы конструкции языка работали.
Соответственно «модификация» очевидным образом ограничена хотя бы тем фактом, что во время исполнения шаблонов нет, а от типов, фактически, остаётся одно название (и то если -fno-rtti не сказали).
То, что вы «вытащите» наружу — вы, во время исполнения, сможете модифицировать. И до переменных добраться и прочее. Уже сейчас много такого можно сделать. Но вот во время компиляции — нет, там многие вещи запрещены (как и вообще в
constexpr
много чего запрещено).А без этого ваши Oxford brackets будут работать… странно: вам придётся куда-то передать список переменных и строки, а потом это всё в рантайме связать.
Насколько это будет полезно — сложно сказать…
Потому что у меня есть опыт написания сериализации хоть в бинари, хоть в JSON, хоть в БД через хаскелевские Generic'и (которые куда слабее TH), равно как и написания библиотек, предоставляющих таковую сериализацию, и получается вполне неплохо.Интересно. Надеюсь что вы не забыли, что в контексте этой ветки «внолне неплохо» == способ, в котором разбирается не только автор, так что сразу вопрос: какое количество людей, кроме вас, пользуется вашей сериализацией и что они о ней думают…
Формализация поведения оператора <=> вручную тоже получилась нечитабельной. Почему нельзя дать пользователю задать критерий сравнения как функцию, которая возвращает некий тип T, для которого однозначно реализованы операторы ==,<,>? Тогда можно было бы один раз посчитать модуль точки и использовать это значение во всех сравнениях.
Когда и в каком сценарии вы будете сравнивать точки в трехмерной системе координат, сравнивая поочередно x, потом y, потом z?Когда захотите засунуть из в std::map, к примеру.
Вот если бы сравнение было по модулю sqrt(x*x+y*y+z*z) я бы еще понял.А этот безумный вариант вы где хотите использовать?
Почему нельзя дать пользователю задать критерий сравнения как функцию, которая возвращает некий тип T, для которого однозначно реализованы операторы ==,<,>?Это лишает затею всякого смысла. Дело в том что на многих процессорах можно достаточно дёшево посчитать <=> для чисел (и не только — см.
strcmp
) — а дальше из «элементарных» построений над числами можно уже построить что угодно.Но ясно же, что на практике всё это будет строиться в основном над строками — где как раз подобные построения уместны и разумны.
P.S. Пример всё равно не очень удачен. Текущее положение дел как-то уж очень страшно описано. Что мешало написать не как на C++98, а как на C++11:
bool operator==(p_ref a, p_ref b) {
return std::tie(a.x, a.y, a.z) == std::tie(b.x, b.y, b.z);
}
bool operator< (p_ref a, p_ref b) {
return std::tie(a.x, a.y, a.z) < std::tie(b.x, b.y, b.z);
}
osyncstream
Не знаток С++, однако есть же мьютексы, зачем городить очередную сущность?
starts_with и ends_with для строк
Давно пора.
Поддержка юникода — классификация символов, поиск/замена, регулярки, конвертация из/в других кодировок. То есть то чем занимается ICU. Но не только — важна поддержка перекодировки для локальных имён файлов/каталогов, например. Или конвертация вывода в std::cout из юникода в локальную кодировку «на лету» и т.п.
На сколько эти все работы завершены и что ещё не сделано?
Сейчас только что посмотрел на сборку Android'а: вся стандартная библиотека (C и C++ вместе) — порядка 2MB, в то время, как только ICU — это две библиотеки на 4MB плюс файл данных на 20MB.
То есть вы хотите из-за того, что вам лично захотелось GUI изобразить увеличить стандартную библиотеку в десять с лишним раз? Губозакатывательные машинки продаются в соседнем отделе.
Вот в виде отдельного опционального TS — пожалуйста, милости просим. А в стандарную библиотеку — ну никак. Извините.
Сегодня, на секундочку, 2017 год и отсутствие такой, в сущности, базовой функциональности это какой-то позор…
Я не вижу никакой проблемы с увеличением размера библиотеки. Для всяких встраиваемых недокомпьютеров (а телефоны к ним не относятся), как уже указал Antervis, вполне можно сделать либо обрезанную библиотеку, либо отдельный модуль.
Решение этой задачи необходимо, конечно же, не только для графического интерфейса пользователя, но практически везде, где есть обработка текста, файловая система или хотя бы текстовые сообщения об ошибках. Не хочу умалять и необходимость стандартной, продуманной библиотеки графического интерфейса пользователя, но это архисложнейшая задача на многие годы вперёд, которая потребует и вышеуказанное.
Для всяких встраиваемых недокомпьютеров (а телефоны к ним не относятся), как уже указал Antervis, вполне можно сделать либо обрезанную библиотеку, либо отдельный модуль.Ну и? Кто будет это делать? Кстати почему это «телефоны к ним не относятся»? ICU отсуствует в Android NDK — ровно по причине того, что её размеры слишком велики, а API имеющейся библиотеки нестабилен (то есть она не может быть частью системы).
Да, там периодически происходят разные разговоры на тему выделения стабильной части, которую уже можно было бы включить в NDK… но пока — это всего лишь разговоры! А вы хотите сразу: бабах — и в ферзи. Извините, но пешка E2-E8 не ходит…
Решение этой задачи необходимо, конечно же, не только для графического интерфейса пользователя, но практически везде, где есть обработка текста, файловая система или хотя бы текстовые сообщения об ошибках.Это с какого-такого перепугу? Файловой системе — это не нужно: при использовании UTF-8 подход «имя файла — это произвольная последовательность байт, не включающая в себя символов '\0' и '\'» — отлично работает. Переводить же низкоуровневые сообщения об ошибках — глупость несусветная: для них главное — возможность засунуть их в Гугл или Яндекс, чем перевод будет активно мешать.
Не хочу умалять и необходимость стандартной, продуманной библиотеки графического интерфейса пользователя, но это архисложнейшая задача на многие годы вперёд, которая потребует и вышеуказанное.Именно потому шансов увидеть и то и другое в стандартной библиотеке — примерно нуль.
Будут модули, будут опциональные компоненты — тогда и можно будет говорить о локализации или графике. А пока — нет.
Ну и? Кто будет это делать? Кстати почему это «телефоны к ним не относятся»? ICU отсуствует в Android NDK — ровно по причине того, что её размеры слишком велики…
Для встраиваемых систем уже есть обрезанные версии библиотек на любой вкус. Для телефонов же 20МБ это не проблема, о чём вообще разговор???
Файловой системе — это не нужно: при использовании UTF-8 подход «имя файла — это произвольная последовательность байт, не включающая в себя символов '\0' и '\'» — отлично работает.
При глобальном использовании UTF-8 никакой проблемы и не возникло бы изначально, но (к сожалению) это не так.
Файловой системе — это не нужно: при использовании UTF-8 подход «имя файла — это произвольная последовательность байт, не включающая в себя символов '\0' и '\'» — отлично работает.
Проблема в том, что не любая последовательность байт является корректной строкой UTF-8. Напомню, что в Linux имя файла — это набор байт, а в Windows — UTF16 (раньше была UCS2). И способов обрабатывать это кросс-платформенно просто не существует.
Проблема в том, что не любая последовательность байт является корректной строкой UTF-8.Однако любая последовательность байт является корректным именем файла.
в Windows — UTF16 (раньше была UCS2).И сейчас, на самом деле, UCS2. Невалидные UTF16-названия файловая система принимает на ура, независимость от регистра тоже распространяется только на символы с кодами до 65535 и т.д. и т.п. Так что… это только всякие диалоги открытия файлов делают вид, что там UTF16.
Если вы GUI не делаете, то и юникод вам, в общем, не нужен.
И способов обрабатывать это кросс-платформенно просто не существует.Ну это к Microsoft'у вопросы.
Она далеко не везде и не во всех применениях базовая. Из личного опыта — оно нужно, наверное, процентах в пяти задач, которые я решаю.У «адептов рефлексии» — оно базовая. Потому что они обьекты с тремя интами через рефлексию создают, блин.
А потом удивляются почему GUI тормозит, да.

За сахаром не видно чая… Интересно, каким образом расставляют приоритеты вводимых в язык фич? Какой смысл набивать его и без того пухлый каркас всё новыми (пусть и полезными) красивостями, когда имеются серьёзные пробоины ниже ватерлинии? За счёт чего будет расширяться комьюнити языка, у которого интеграция нового пакета — задача из категории стыковок космических станций? Кто будет выбирать язык, в котором десятистраничные ошибки генерации типов во время компиляции — это норма? Вряд ли за счёт добавления щепотки новых сладеньких конструкций С++ станет привлекательнее для неофитов. А без свежей крови языки становятся латынью.
Я очень люблю С++ и рад, что он пока худо-бедно держится на пятых местах всяких рейтингов. Однако каждый новый стандарт заставляет грустить. Не тем козыряют, как по мне. Совсем не тем, чем следовало бы.
Кто будет выбирать язык, в котором десятистраничные ошибки генерации типов во время компиляции — это норма?
Должно быть починено Concepts TS, уже будет в C++20.
За счёт чего будет расширяться комьюнити языка, у которого интеграция нового пакета — задача из категории стыковок космических станций?
Это общая проблема всех языков программирования. И никакой пакетный менеджер это не решает, ошибки с pip/maven/gem/conan всё еще проще чинить копированием нужного пакета в репозитарий и выкидыванием пакетного менеджера.
Это общая проблема всех языков программирования.
Нет, не любого. В том же C#, например, для подключения библиотеки достаточно одного файла — сборки. В C++ же такой фокус не прокатит — изволь тащить с собой все хедеры, исходники или статические либы, причём последние не только системо-, но и компиляторозависимы. Ещё надо не забыть про условную компиляцию и скорость этой самой компиляции.
А я и не сравниваю компиляцию во время выполнения со статической компиляцией. Я лишь указываю на то, что сам процесс компиляции С++ очень болезненнен и неэффективен.
В шарпике цена абстракций перекладывается на рантайм
Главное премущество C#, да и Java — мухи (язык программирования) отдельно, котлеты (VM) отдельно.
Было бы удобно, если бы либы распространялись не в виде хедеров/исходников, а виде предкомпилированных платформо-независимых модулей. Тот же clang сначала компилирует в LLVM, а уже потом генерит нативный код.
Тот же clang сначала компилирует в LLVM, а уже потом генерит нативный код.Вот только AST clang'овский зависит как от версии компилятора, так и от целевой платформы. И да, сделать его переносимым не так-то просто, замедление получается весьма заметным.
Не спорю. C/C++ рассматривается как язык под любую платформу и железку.
Но я уверен, что конкретно под массовые платформы x86/x64/ARM64 решение придумать можно.
Но я уверен, что конкретно под массовые платформы x86/x64/ARM64 решение придумать можно.Вы вообще сколько с компилияторами общались, извините? Откуда эта уверенность взялась? Рассмотрите простую программу:
struct Point {
int x;
int y;
};
extern void Do_Something(Point what, int how);
void Adapter(int x, int y) {
Do_Something({x, y}, 42);
}
Так вот на x86 вам нужно будет вынуть два числа со стека, засунуть туда 42, после чего добавить туда же x и y, на ARM — нужно будет просто записать в r2 42 и сделать jmp
, на x86-64 — вам нужно будет скомбинировать два аргумента в один. Да, ёлки ж палки — посмотрите сами! И? Как вы это всё в одно AST собрались засовывать?Нет, это сделать можно (а в программировании вообще мало чего нельзя сделать в принципе, никогда) — но это полкомпилятора придётся переделывать!
Вся информация — описана в Википедии — это не какая-то супесекретная информация…
И это — ещё простой случай! А рассмотрите вариантик посложнее:
#include <cstdio>
template<int n> struct confusing
{
static int q;
};
template<> struct confusing<4>
{
template<int n>
struct q
{
q(int x)
{
printf("Separated syntax and semantics.\n");
}
operator int () { return 0; }
};
};
int main()
{
int x = confusing<sizeof(x)>::q < 3 > (2);
return 0;
}
Ничего что у вас на x86 confusing<sizeof(x)>::q
— это функция, а на x86-64 — переменная. Нормально так? Всё ещё горите желанием придумать решение «под массовые платформы x86/x64/ARM64»?Нет уж, извините. Либо у вас ваши модули будут, фактически, ахивами со слегка обработанными исходниками, либо вам весь язык придётся переделывать. Снизу доверху.
p.s. и в x86 и в x86-64 sizeof(int)==4 тут бы сравнивать size_t/ptrdiff_tДа, извиняюсь, недоглядел. Спрасиба за замечание.
Переделывать придется только фронтенд компилятора на работу с AST/ir, который это допускаетПроблема в том, что «AST/ir, который это допускает» — это, фактически, голая последовательность токенов и всё. При желании можно устроить программу, которую можно распарсить только на платформах, удовлетворяющих какому-нибудь хитрому условию.
«Ничего что у вас на x86 confusing<sizeof(x)>::q » ничего, кода в модуле нет, символы останутся оба, оптимизатор AST/ir скипнет это нафиг на этап кодогенкрации, кодогенератор подставит то что нужно в зависимости от sizeof.До этапа кодогенерации ещё дожить надо — а вы пока не рассказали, как вы AST строить собрались, если для синтакцического разбора нужно умеить решать уравнения на эллиптических кривых — причём со входными данными, приходящими от целевой платформы.
Не забудьте, что там вместо банального
sizeof
может стоять вызов любой constexpr
функции, а дальнейшее дерево зависит от результата вычислений оной функции.clang-format имеет много подобных чудес, так как разобрать (то есть даже синтаксически разобрать, просто АСД построить!) программу на C++ можно только имея информацию о той платформе, на которой вы программу хотите запускать.
Во время кодогенерации эта шняга проходится, и тупиковый вариант выкидывается.
Вроде тупые оптимизации ast а ля пропагация констант, сворачивание методов, эта штука может переживать, про сложные сказать не могу.
С constexpr тоже самое.
«При желании можно устроить программу, которую можно распарсить только на платформах, удовлетворяющих какому-нибудь хитрому условию.»
можно, в этом случае будет колбаса-последовательнось токенов, которая в конце будет содержать кучу листов c guardами идущих в разобранные методы. Длина колбасы может быть большой, но и с текущей ситуацией есть template бомбы, от которых и gcc,clang,msvc тупо дохнут, кто же спорит, вопрос насколько это часто встречается на практике
Я если честно всё равно не въехал в чём проблемаА я не могу понять чего вы не понимаете. Но попробую разобрать подробнее. У меня есть ощущение, что вы краем глаза на пример взглянули и даже не подумали о том — какое здесь будет AST.
А проблема в том, что дерево будет разным. Ну вот совсем разным.
В одном случае q — это шаблонная функция. И в AST это будет примерно представлено как:
function: name = "q" children: specialization - "<3>" parameters: "2"
В другом случае — это переменная. И AST будет примерно таким:
operator: name = ">" children: left: "q < 3" right: "(2)"
Ну и, понятно, левое выражение тут — это тоже operator (с именем "<" и двумя аргументами — «q» и «3»).
Понимаете? У вас не просто типы нод в AST отличаются! У вас структура AST отличается! В одном случае «наверху» — функция "
q
" и у неё два ребёнка (специализация <3>
и параметры (2)
), в другом — это "operator>
" и него два других ребёнка (ещё пара выражений — q<3
и (2)
).И для того, чтобы сделать выбор — вам нужно знать: была выбрана частичная специализация — или нет.
Да чёрт с ним, этим примером — он специально сделан так, чтобы оба варианта были валидны.
Что ваш компилятор должен сделать с кодом:
int x = confusing<sizeof(x)>::q<3;
или с кодом
int x = confusing<sizeof(x)>::q<3>;
Ведь в зависимости от того что такое есть
q
— этот код может быть валидным или не валидным! А если этот x
— у вас constexpr
, то это может сделать валидным/невалидным что-то ещё. И так далее, по цепочке.Вроде тупые оптимизации ast а ля пропагация констант, сворачивание методов, эта штука может переживать, про сложные сказать не могу.Какие, к бесу, «тупые оптимизации» вы собираетесь производить, если вы дерево разбора, блин, построить не можете! Вы не знаете — что есть что в этой конструкции! Функция, оператор, шаблон — что где, как с этим жить? Ничего не известно!
Длина колбасы может быть большой, но и с текущей ситуацией есть template бомбы, от которых и gcc,clang,msvc тупо дохнут, кто же спорит, вопрос насколько это часто встречается на практикеСплошь и рядом. Ситуация когда код нормально работает на ILP32 и даже не парсится LP64 (или наоборот) — вполне типичны. А ещё больше случаев когда код таки парсится — но по другому и в результате не компилируется.
Проблема в том, что грамматика C++ очень сильно зависит от контекста. Угловая скобочка может быть либо угловой скобкой, либо банальным опереатором меньше. Скобки могут использользоваться для указания параметров функции, либо просто для залания проиритетов операций. А уж сколько всего весёлого бывает с фигурными скобками!
Чтобы правильно всё это распарсить вам нужно знать — какие частичные специализации отработали, а какие нет. И что они вернули.
Вы же предлагает всё это отложить на момент, когда библиотеку будут пытаться использовать. Плохое решение. Не всем нужен LTO и не все могут себе его позволить. И ещё меньше кому нужна «работающая» библиотека, которую нельзя подключить, так как из неё вдруг ошибки компиляции лезут.
Можно, наверное, опять-таки, разработать некоторый диалект языка C++, где этих проблем не будет — но это отдельная история и даааалеко не факт, что этот диалект будет популярен…
Будет expression:«confusing<sizeof(x)>::q<3>»
children «confusing<sizeof(x)>::q<3 >» gurard:«sizeof(int)=4»
children «confusing<sizeof(x)>::q<3>» guard:«sizeof(int)!=4»
«Проблема в том, что грамматика C++ очень сильно зависит от контекста» Да зависит, но это не значит что ничего вывести доступных на момент компиляции ограничений нельзя.
Напомню что синтаксис определяется грамматикой, а вот интерпретация этого синтаксиса семантикой, грамматика у cpp вроде как контекстно-свободная.
«Вы же предлагает всё это отложить на момент, когда библиотеку будут пытаться использовать.»
А типа сейчас не так? в простынях ifdefов и шаблонов наружу?
Причём тут lto мы компилируем единицу трансляции, если компилируем в обычном режиме, то компилятор тупо вырезает неверные пути из ast и спамит ошибками если достижимы вершины с ошибками, если lto то будет больше проходов
bison
'а отказался и у clang'а свой собственный «ручной» парсер.Можете на stack overflow почитать — там формально доказывается, что грамматика не просто не является контекстно-свободной, а она вообще — полна по Тьюрингу! То есть мы в принципе не можем понять — будет данная программа синтаксически валидна на всех платформах или нет.
И нет — речь не идёт о том, чтобы разобраться с семантикой. Речь именно о парсинге.
А вот есть ещё чудесный пример где AST некоторого участка C++ кода зависит от описания typedef'а случившегося после этого участка кода.
Какая тут, нафиг, контекстно-свободность…
А ещё есть, кстати, моё любимое, вот уж где вынос мозга и полный ад, ад, адище.А его, кстати, не закрыли в C++17? Вроде ж как собирались…
Рекомендую переписать то, что вы написали 100 раз на доске, читая то, что вы написали — вслух и с выражением.
«грамматика у cpp контекстно-свободная»… «зависит от контекста»…
«зависит от контекста»… «контекстно-свободная»…
«контекстно-свободная»… «зависит от контекста»…
Я не знаю, блин, сколько раз нужно прочитать эти две фразы, но после какого-то повторения (может быть 1000го) до вас должно-таки дойти, что «контекстно-свободная» и «зависит от контекста» — это таки две несовместимых вещи!
Вроде обсуждается C++, причём на полном серьёзе, а элементарных вещей об этом языке — вы не знаете. Или, вернее, не хотите знать. Даже когда вас в них буквально «тыкают носом».
Нет, грамматика C++ не является контекстно-свободной. Причём категорически не является. Она настолько не является контекстно свободной, что об этом, вроде бы, должны знать все, кто работает с C++. Но, как мы видим, некоторые умудряются остаться в счастливом неведении.
Простейший, блин, вопрос на собеседовании. Рассмотрим такую функцию:
template<class T>
auto my_begin(T& t) {
typename T::iterator i = t.begin();
return i;
}
Зачем у нас в третьей строчке написано слово typename
и почему без него нельзя обойтись?Ответ: потому что грамматика C++ не является контекстно-свободной и для того, чтобы шаблонную функцию вы вообще смогли распарсить вам нужно указать контекст: является ли тот или иной идентификатор обычной переменной, типом (указывается с помощью
typename
), или шаблоном (указывается с помощью template
.Но в случае, если код — не шаблонный такой информации у компилятора нет и он должен выяснять — к какому из трёх классов относится тот или иной идентификатор задействуя дополнительную информацию из семантики C++.
В примере, который я привёл в зависимости от контекста вы либо парсите кусок кода как вызов
operator>
от вызов operator<
— либо просто как вызов фунции. Куда уж дальше-то на дорожке к контекстной несвободности?А типа сейчас не так? в простынях ifdefов и шаблонов наружу?В случае с шаблонными библиотеки, поставляемые в исходниках — да, так и есть. Но подавляющее большинство библиотек — устроены не так.
Причём тут lto мы компилируем единицу трансляции, если компилируем в обычном режиме, то компилятор тупо вырезает неверные пути из ast и спамит ошибками если достижимы вершины с ошибками, если lto то будет больше проходовПроблема в том, что в любой достаточно сложной программе на C++ всегда есть какие-то «вершины с ошибками». То ли у вас шаблоны «не так» инстанциируются, когда «sizeof(void*)» != «sizeof(long)», то ли у вас специализации под «signed char» нет, то ли ещё какая бяка случается.
Сейчас такой код тупо компилируют на нескольких платформах и если на всех «нужных», при данных на них параметрах платформы всё парсится и собирается — то и хорошо. А появится ещё какая-нибудь платформа — выпустим
patch
. Половина ошибок в boost
е этому посвящена.Вы же хотите заставить людей писать код, который гарантированно распарсится и соберётся под любую платформу, блин.
Где вы таких программистов найдёте? Тут никак убедить писать программы без UB не удаётся — а вы хотите заставить все существующие программы переписать с полноценной разметкой
typename
и template
в каждой второй строке.Никто не будет этого делать, тут даже обсуждать нечего.
По крайней мере, алгоритмических причин так не делать я не вижу.А я вижу: у компилятора появляется вначале два, потом (на второй развилке) четыре и так далее способов разобрать выражение — а экспонента растёт уж дюже быстро.
Людей, которые считают, что C++ компилятор уж как-то слишком быстро работает и нужно бы в него так, походя, вкрутить экспоненту — я ещё не видел.
Какие-нибудь реально вполне несложные того типа, о котором вы говорим встречаются чаще, чем вам кажется. Обычно в контексте типа:
f (i < x, y > (j+1))
Хватит с нас одного языка для потребителей кофе.Будет expression:«confusing<sizeof(x)>::q<3>»Только заметил.
children «confusing<sizeof(x)>::q<3 >» gurard:«sizeof(int)=4»
children «confusing<sizeof(x)>::q<3>» guard:«sizeof(int)!=4»
О боги олимпа! Откуда у вас в строке с «sizeof(int)!=4» взялась строка «confusing<sizeof(x)>::q<3>»?
В том-то и дело, что если sizeof(int)==4, то строка у нас разбивается при разборе на следующие три куска:
«confusing<sizeof(x)>::q» «<3>» и «(2)»
А если sizeof(int)!=4, то всё будет по-другому, куски будут такие:
«confusing<sizeof(x)>::q<3» «>» «(2)»
Вы не сможете в варианте с sizeof(int)!=4 ничего приписать выражению «confusing<sizeof(x)>::q<3>», потому что там нет этого выражение. Там другое дерево разбора и знак больше — уехал вообще в другу ноду!
Ничего что у вас на x86 confusing<sizeof(x)>::q — это функция, а на x86-64 — переменная. Нормально так? Всё ещё горите желанием придумать решение «под массовые платформы x86/x64/ARM64»?
Увидительно, что ни один компилятор ещё не дорос до того, чтобы во всех случаях свести программу к пустой — ведь программа ничего не вводит и ничего не выводит.
В любом случае, путь к универсальному LLVM под основные платформы я считаю наиболее разумным.
Правда, теперь мне стало интересно, как вообще представляется AST в компиляторах плюсовКак представляется — это не так интересно. AST как AST, там ничего суперхитрого нету.
учитывая, что парсинг плюсов не что что контекстно-зависим, а вообще полон по Тьюрингу (и с учётом вот приведённых вами случаев).А вот это вот — другой вопрос. GCC какое-то время пытался бороться с
bison
'ом, обвешивая его хуками, но в конечном итоге сдался. А в clang'е — с самого начала всё было под «работу на разных уровнях» заточено.Насколько мне известно все парсеры C++ в современных компиляторах написаны руками и могут вызывать более поздние стадии (включая выполнение
constexpr
-функций, да). А иначе никак — иначе C++ не распарсить.То есть в компиляторах C++ нет (и не может быть) отдельной стадии построения AST. Фактически парсер и компилятор работают как сопрограммы (хотя оформлено это в разных компиляторах по разному).
Это в каком-то смысле и значит, что у вас AST никак толком не представляется, ибо ни в какой момент времени он не материализован полностью (в общем случае).Что значит «ни в какой момент времени он не материализован полностью»?
Он вполне себе материализован к моменту, когда к нему можно обращаться — откуда, как вы думаете, более поздние стадии получают информацию о коде?
А полная материализация, как и положено, происходит к моменту окончания работы парсера — просто некоторые вещи можно делать до окончания этого процесса (как им, скажем,
constexpr
функции исполнять если они AST читать не могут?).Они просто используют ту часть, которая уже построена. Делов-то.
Все эти проекты упираются в одну простую вещь: им приходится язык очень сильно изуродовать. Существующие библиотеки с этим делом особо не поиспользуешь (я имею в виду уже собранные и присутствующие в системе), часть возможностей языка отсутствует — и нафига оно такое кому нужно? Очередной C++/CLI? Так один уже есть…
Один из этапов компиляции — парсинг «тяжелых» заголовочников для каждой единицы трансляции и так будет оптимизирован с появлением модулей.
Единственный плюс вашего предложения — один файл вместо набора заголовочников + динамических библиотек. Тогда уж проще договориться о том, чтобы поставлять модули в виде несжатых архивов с определенной иерархией размещения файлов.
Вообще нельзя говорить о решении проблем поддержки кучи компиляторов и платформ, приводя в качестве примера яп с одним компилятором и одной платформой. Java в этом плане тоже недалеко ушел.
Так а какой выигрыш тогда будет получен?
Удобство подключения библиотек, более компактное их представление.
В идеале, промежуточное представление должно быть компиляторо-независимо.
Сериализация и десериализация промежуточного представления займет дополнительное время, а основной по времени этап — линковка + LTO не сократится.
Да, LTO — самая долгая процедура, и ничего с этим не поделать. Это цена за генерацию эффективного кода.
Но для отладочных билдов самая долгая процедура — парсинг инклюдов.
И серализация/десериализация промежуточного представления даёт ощутимый выигрыш, иначе бы не было плясок с PCH.
Один из этапов компиляции — парсинг «тяжелых» заголовочников для каждой единицы трансляции и так будет оптимизирован с появлением модулей.
Я не был бы настолько оптимистичен здесь. Legacy-код и единицы трансляции все равно останутся. Пройдёт много времени, прежде, чем модули станут по-настоящему эффективны.
Единственный плюс вашего предложения — один файл вместо набора заголовочников + динамических библиотек. Тогда уж проще договориться о том, чтобы поставлять модули в виде несжатых архивов с определенной иерархией размещения файлов.
Ну хотя бы так. И чтобы зависимости описывались максимально просто — названиями пакетов.
Вообще нельзя говорить о решении проблем поддержки кучи компиляторов и платформ, приводя в качестве примера яп с одним компилятором и одной платформой. Java в этом плане тоже недалеко ушел.
Java как раз таки работает на огромном числе платформ, и существует много ЯП, которые компилируются в код VM и совместимы с Java.
И серализация/десериализация промежуточного представления даёт ощутимый выигрыш, иначе бы не было плясок с PCH.
Не путайте. PCH парсится во внутренее представление компилятора (он бы и так и эдак туда парсился). Вы говорите о компиляторонезависимом представлении.
Ну хотя бы так. И чтобы зависимости описывались максимально просто — названиями пакетов.
пользуйтесь conan, например. conan install --build-missing разрешит зависимости для всех популярных пакетов.
Java как раз таки работает на огромном числе платформ
Java работает только основных десктопных и мобильных платформах. Без embedded.
Не путайте. PCH парсится во внутренее представление компилятора (он бы и так и эдак туда парсился). Вы говорите о компиляторонезависимом представлении.
Это был контраргумент на "Сериализация и десериализация промежуточного представления займет дополнительное время". Я утверждаю, что это, наоборот, даёт выигрыш в итоге.
пользуйтесь conan, например. conan install --build-missing разрешит зависимости для всех популярных пакетов.
Хочу ещё проще. Реформу самой системы описания проекта и его сборки.
Java работает только основных десктопных и мобильных платформах. Без embedded.
Сравните доли разработки под x86/x64/ARM/ARM64 со встраиваемыми решениями. Удобное решение под 99% случаев будет всяко лучше, чем неудобное, но покрывающее 100%.
Сравните доли разработки под x86/x64/ARM/ARM64 со встраиваемыми решениями.На C++-то? С учётом всяких Arduino и прочих STM32? Думаю 50/50 будет. А то и вовсе может оказаться, что x86/x64/ARM/ARM64 окажется в меньшинстве.
Да и не стоит валить x86/x64/ARM/ARM64 в одну кучу: как я уже писал выше — поддежать хотя бы x86 и x86-64 одновременно это уже огромная проблема. Из неё, собственно, небезизвестный продукт вышел.
Удобное решение под 99% случаев будет всяко лучше, чем неудобное, но покрывающее 100%.Создадите «удобное решение» хотя бы для x86 и x86-64 — заходите, будет о чём поговорить. А там — мы ещё 10 диалектов одного ARM'а подтянем (OABI, EABI, HARD-FP, SOFT-PF и всё такое прочее).
Увы и ах, но Java — это очень и очень тяжёлое решение, попытки её аппетиты немного урезать приводит к тому, что бо́льшая часть техник перестаёт работать и, фактически, даже низкоуровневые библиотеки использовать невозможно.
Однако каждый новый стандарт заставляет грустить.Грустить из-за чего? Тут когда из C++14 в C++11 возвращаться приходится, то уже неприятно, хотя C++14 — это совсем небольшой шаг вперед в сравнении с C++11. А уж когда нужно в C++98 окунуться, так вообще как будто в каменный век возвращаешься.
Не тем козыряют, как по мне. Совсем не тем, чем следовало бы.А чем следовало бы?
Грустить из-за чего?
Из-за того, что обсасывают в основном всякий сахар и введение классов из boost в std. У меня, возможно, мало опыта (объясните если не прав) — однако я не понимаю в чём первостепенная важность переноса классов из плейграундов вроде boost в стандартную библиотеку (насчёт переноса type traits ясно — это временные костыли для рефлексии). В плюсах имеются практически бесплатные абстракции и мощная условная компиляция. Эти механизмы позволяют упростить вопросы стандартизации API.
До ввода тех же классов многопоточности в стандарт люди писали обёртки. После явления в std нужных классов миграцию выполняли через замену условной компиляции на новые классы стандарта с последующей подгонкой API и полной заменой обёрток на соответствующие классы из std.
Если что — я говорю тут не про умные указатели, а именно про классы, не связанные напрямую с информацией, полезной на этапе сборки (тут не очень ясно выразился — надеюсь, понятно что я имею в виду)…
Был бы благодарен за объяснение если я что-то тут не так понимаю.
А чем следовало бы?
Вещами, работающими не на ублажение тонких нужд и ленивостей прожжённых пользователей (подчеркну — именно тонких нужд, вроде того же оператора spaceship), а на снижение порога вхождения в экосистему. Чем больше пользователей у языка — тем выше динамика развития экосистемы и тем выше значение языка. С теми же пакетами логика элементарна: из-за сложности интеграции пакетов сплошь и рядом решения велосипедятся, порождая дублирование кода. Да, часто утверждается что истинная причина самописностей — тонкая оптимизация. Мол, язык такой. Нужно тюнинговать детали под себя… Однако если бы пакеты внятно подтягивались — на плюсах писалось бы больше прикладного кода с повторным использование библиотек, что положительно влияло бы на экосистему в целом и на качество пакетов в частности. Люди смелее выбирали бы из разных вариантов при подключении функционала, динамичнее была бы конкуренция между разработчиками пакетов.
Я не на ровном месте пишу всё это. Кого не спрашиваю из боящихся входить в язык или ушедших с него: не нравится сложность интеграции пакетов, пугает сложность шаблонов (не в последнюю очередь — из-за сложности отладки… ну, про это написали — спустя десятилетие наконец-то как бы приходят концепты), пугает загромождённость языка фичами… Особенно впечатляет, когда некоторые пишущие на С++ гордятся тем, какой у них сложный и запутанный язык.
В частности всё, что вы описали — отсюда, собственно.
если бы пакеты внятно подтягивались…
Microsoft: ну понятно же — nuget — наше все.
Debian: вы, что, оху-, нет, охре-, нет… совсем белены обьелись? C# для работы с пакетами на C++? Вот, отличное решение.
Gentoo: Это чтобы одну опцию переключить вам нужно исходники править? Да это вы тут белены обьелись! Вот у нас — всё пучком.
Google: Ну нет, так мы не договаривались. В ваших этих shell-скриптах утонуть можно. Вот же есть простая система.
Android: какая ж она «простая», если даже библиотеку под две платформы собрать — проблема? Вот у нас — всё очень гибко где нужно и прямо — где не нужно.
Ну и так далее.
И это я ещё всяких мелких вендоров не вспомнил…
В том-то и дело, что надстройка — у C++ одна (хотя и большая), а того, что «ниже ватерлинии» — десятки, если не сотни!
Ну и что тут комитет по стандартизации может сделать? Да любое предложение будет до конца века обсуждаться!
Из-за того, что обсасывают в основном всякий сахар и введение классов из boost в std.Ну вот даже тут, в комментариях уже прозвучала мысль о том, что variadic templates в С++ — это всего лишь синтаксический сахар. Возможно, эту мысль распространяют мегагуру, которые и на C++98 с Boost.Preprocessor в обнимку могли генерировать имитацию шаблонов с переменным количеством параметров. Но вот для простых смертных variadic templates стали тем, что перевело использование таких шаблонов из области высокой теории в область обыденной практики. Аналогично и с лямбдами: кто-то мог написать свой Boost.Lambda и получал от этого кайф, кто-то мог использовать Boost.Lambda и мог думать, что в языке лямбды уже есть. А для кого-то лямбды, которые можно просто брать и использовать, появились только с C++11.
Что до переноса классов из Boost-а в stdlib, то одна из задач stdlib — это предоставление словаря, который могут использовать разработчики сторонних библиотек/компонентов. Чтобы если в библиотеке A создается умный указатель на хэш-таблицу, а в библиотеке B этот указатель используется, программистам не приходилось делать конвертеры из типов библиотеки A в типы библиотеки B (а для С++98 это приходилось делать постоянно). Так что это хорошо, что список типов в stdlib постоянно расширяется и туда попадает то, что уже было проверено на практике.
тут не очень ясно выразился — надеюсь, понятно что я имею в видуНе понятно.
Вещами, работающими не на ублажение тонких нужд и ленивостей прожжённых пользователей (подчеркну — именно тонких нужд, вроде того же оператора spaceship), а на снижение порога вхождения в экосистему.По моему опыту, как раз то, что добавили в C++11, самым значительным образом упростило вход в язык программирования.
Что до экосистемы в целом, в том числе до пакетного менеджера, то здесь возможности коммитета ограничены в принципе. Добавим сюда еще и то, что передача развития C++ под работу коммитета произошла очень давно (начало работы коммитета — это 1989-1990-й годы). Тогда такой проблемы не существовало в принципе. И нужно было увидеть, как развиваются другие языки и экосистемы, чтобы осознать важность build tool-ов и package manager-ов. И как раз в этом направлении в C++ движуха сейчас активна как никогда. Возможно, даже коммитет начнет в этом направлении что-то делать.
А вообще: язык развивается за счет своего коммьюнити. Если вам лично нужно что-то, то вы сами можете предложить то, что вам нужно. Если вы этого не хотите/не можете сделать, то, поскольку язык развивается сообществом, вы будете пользоваться тем, что предложили и продвинули другие.
Возможно, даже коммитет начнет в этом направлении что-то делать
Думаю, меня и других страдальцев расстраивает то, что в публикациях мало выделяются подвижки в интересующих нас направлениях. Тема модулей и менеджеров пакетов стабильно обсасывается в комментариях — однако крайне редко мелькает в самих публикациях.
Глянул даты выходов пакетных менеджеров для ведущих языков. Действительно, пакетные менеджеры NPM (для Java Script) и PIP (для Python) вышли в районе 2010 года. Однако Maven (для Java) существовал с 2004 года… Можно ещё вспомнить — пусть и не совсем по теме — пакетные менеджеры Linux. Важность упрощения подключения модулей и сборки мультимодульного проекта, как по мне, очевидна. Данный вопрос не возник внезапно когда другие языки начали выкатывать свои менеджеры.
Ну вот даже тут, в комментариях уже прозвучала мысль о том, что variadic templates в С++ — это всего лишь синтаксический сахар
Тут абсолютно согласен с вами. Упрощение метапрограммирования — важное направление, и тут мы так же очень долго ждём концептов. Про лямбды — тоже согласен. Это было важное нововведение. Они выступают главным блочком одной из парадигм программирования.
Однако С++11 де юре вышел шесть лет назад. Для индустрии это громадный срок. И с тех пор подвижки как-то забуксовали.
Что до переноса классов из Boost-а в stdlib
Ага… Аргумент про преобразование типов хороший, спасибо.
Не понятно
Да, тут какую-то глупость написал… Пытался сформулировать принцип проведения границы между более и менее важными классами для перенесения в stdlib (как по мне, тут включение многопоточности менее важно, включение умных указателей — более важно). Сформулировать плохо получилось.
язык развивается за счет своего коммьюнити
Аргумент из категории «в начале сними лучше, а потом критикуй кино» — но отчасти справедливо.
Я пробовал писать свой пакетный менеджер, а также некоторое время пробовали разрабатывать пакетный менеджер совместно с товарищем theambient. У нас возникли разногласия — theambient продолжил работу над своим менеджером сам, а я немного со своим поковырялся, споткнулся о шаблоны и поставил работу над проектом на долгую паузу.
В данный момент я с переменным успехом штурмую совершенно другую индустрию. Если не выйдет и доведётся-таки выбирать программирование делом жизни — буду бороться за пакетные менеджеры).
Пытался сформулировать принцип проведения границы между более и менее важными классами для перенесения в stdlib (как по мне, тут включение многопоточности менее важно, включение умных указателей — более важно).С многопоточностью ситуация забавная. Появление модели памяти и mutexов и atomicов, позволяющей писать переносимые библиотеки, надёжно работающие в многопоточном окружении — черезвычайно важно, важнее, чем появление «умных указателей». А вот собственно примитивы для работы с потоками — не так важны.
Но, согласитесь, было бы глупо если бы язык предоставил mutex'ы и atomic'и — но не предоставил никакого способа создать поток… Считайте, что thread вы получили «в нагрузку»…
Тема модулей и менеджеров пакетов стабильно обсасывается в комментариях — однако крайне редко мелькает в самих публикациях.А чему тут мелькать? Работа вокруг Modules TS активно идет. Экспериментальную поддержку модулей делают в VC++, clang и GCC. В инструменте для сборки проектов build2 даже реализовали поддержку проектов с C++ными модулями. В общем, работа кипит. Просто ее результаты пока промежуточные и не видны широкой публике.
С менеджерами зависимостей сейчас вообще активная движуха. Такой еще никогда не было в мире C++. Проблема только в том, что не понятно, кто победит :)
Можно ещё вспомнить — пусть и не совсем по теме — пакетные менеджеры Linux.Как по мне, так это одна из основных причин, по которым штатного менеджера зависимостей для C++ пока нет: огромное количество C++ников разрабатывает код исключительно под Unix-ы и принципиально не желает пользоваться чем-то отличным от штатных пакетных менеджеров их любимых дистрибутивов. И их не волнуют, что есть другие дистрибутивы с другими менеджерами. И уж тем более их не волнуют другие ОС.
Однако С++11 де юре вышел шесть лет назад. Для индустрии это громадный срок. И с тех пор подвижки как-то забуксовали.Для индустрии шесть лет — это не так уж и много. Даже если сравнивать с возрастом самого С++. Есть куча проектов, которые даже не начинали на C++11 переводить. И, подозреваю, часть из них так и не переведут.
Кроме того, что значит «забуксовали»? Стандарты стали выходить каждые 3 года. Такого в мире C++ еще никогда не было. Но, что еще более важно, начиная с C++14 стала происходить совсем уникальная штука: поддержка нового стандарта практически сразу была доступна в мейнстримовых компиляторах к моменту публикации официального стандарта. VC++ здесь, конечно, был позади GCC и clang, но уже для C++17 обещает серьезно подтянуться.
VC++ здесь, конечно, был позади GCC и clang, но уже для C++17 обещает серьезно подтянуться.
судя по текущему состоянию дел, он скорее не подтянется, а еще больше отстанет. clang/gcc уже несколько месяцев поддерживают c++17 полностью, в то время как судя по mdsn поддержка с++17 в последней студии примерно на 50%
Во-вторых, по сравнению с тем, как быстро появлялась поддержка предыдущих стандартов в VC++ (начиная с C++98) — это все просто огромный прогресс для VC++.
Во-первых, у вас устаревшая информация о том, как развивается поддержка современного C++ в VC++: инфа от 15-го ноября сего года.
With VS2017 version 15.5, MSVC has implemented about 75% of C++17 core language and library features
Всё равно далеко не в лидерах.
Всё равно далеко не в лидерах.Подтягиваться:
1. Медленно перемещаясь, приближаться к чему-либо.
2. Догонять ушедших вперед, подтягивать отставших.
Где вы тут лидерство увидели?
P.S. Вообще-то знание языка на котором ведётся дискуссия — необходимое условие для того, чтобы её можно было вести… ну так считается.
Ещё один шажок к C++20. Встреча в Альбукерке