В интернетах периодически можно видеть обсуждения а не добавить ли в C механизм defer? И там тоже половина воспринимает идею в штыки, мол не надо в наш простой и понятный C тащить всякие неявные defer, есть же goto.
И вот представляется мне как разработчики на Go смотрят на это и думают, вот чудные, такой простой, понятный и удобный механизм не хотят использовать. А потом переключаются на соседнюю вкладку и критикуют синтаксический сахар обработки ошибкок, мол не надо в наш простой и понятный Go тащить всякие неявные try, есть же if =).
На это смотрят разработчики например на Rust и думают, вот чудные, такой простой, понятный и удобный механизм не хотят использовать. А потом переключаются на соседнюю вкладку и...
размер пикселя это тупо квантовая эффективность оного
Квантовая эффективность -- это процент фотонов, которые были преобразованы в электричество, от общего числа поглощенных фотонов.
Один большой пиксель некоторой площади поглотит и преобразует то же самое количество фотонов, что и несколько более мелких пикселей суммарно той же самой площади.
Поэтому в отрыве от контекста кажется ну вот же, один большой пиксель шумит меньше -- значит это лучше, а по факту общее количество информации и суммарный сигнал/шум всего изображения остаются одни и те же.
Одна беда, съёмка при недостатке освещения, всё расставляет по местам ибо против физики с математикой не попорешь
Но недостаток света и результирующий шум всего изображения целиком не коррелирует с размером пикселя. Если бы вместо 200 МП сенсора использовали 50 МП сенсор -- результат был бы точно тот же самый.
Причем в данном случае практически буквально. С учетом той оптики, которая используется в смартфонах (в первую очередь f-число) оптическая система модуля камеры с сенсором такого размера (порядка 1/1.4") оказывается диффракционно ограничена примерно 50 МП.
если речь о пространствах яркости и цвета, во времена аналогового видео и не такое жрали
Я вам по секрету расскажу =) практически все изображения и видео (подавляющее большинство популярных форматов и кодеков) и по сей день это отдельные пространства яркости и цвета с пониженным разрешением (дискретизацией) цвета.
для крупных пикселов есть свои достоинства (выше чувствительность, меньше шумы)
Это может быть несколько контринтуитивно, но при всех прочих равных размер пикселя играет мало роли.
Да, большой пиксель как будто бы менее шумный, но конечное изображение будет выглядеть по сути одинаково независимо от того, будет оно составлено из меньшего количества менее шумных пикселей или большего количества пропорционально более шумных пикселей.
Собственно это и позволяет производителям смартфонов творить такую лютую дичь, как использование 200 МП сенсора -- в итоге работать он будет плюс-минус так же, как и 24 МП сенсор того же размера. По той же причине полнокадровая камера высокого разрешения (например Sony A7RV с 61 МП матрицей) показывает такое же качество изображения, как и полнокадровая камера меньшего разрешения (например, Sony A7III с 24 МП матрицей) при существенно меньшем размере пикселя.
Потому что если самую чуточку упростить, качество всего изображения упирается в два фактора: количество проецируемого света (фотонный шум) и схемотехника сенсора (электронный шум). А размер пикселя дело десятое.
А для сенсоров одного технического поколения-исполнения все и вовсе упирается в количество света. Поэтому пытаются либо увеличить размер сенсора (чтобы впитать больше света при одинаковой светосиле объектива), либо увеличить светосилу объектива (чтобы спроецировать больше света при одинаковом размере сенсора), либо и то, и другое одновременно. Ну и еще иногда делают что-нибудь такое эдакое с самим сенсором, но это в последнее время редкость.
за счет быстрого съема изображения можно позже программными методами повышать разрешение итогового изображения - Pixel Shift
Тут есть нюанс: это мало подходит для съемки сцен, в которых присутствует движение, даже такое небольшое как колышащиеся на ветру ветки деревьев. Многие камеры имеют режим Pixel Shift и обычно он подходит для съемки только полностью статичных объектов.
VirtualBox через Hyper-V работает со скоростью черепахи, они даже иконку соответствующую при этом в трее рисуют.
Из документации к последней версии:
Oracle VirtualBox can be used on a Windows host where Hyper-V is running. This is an experimental feature. <...> Note: When using this feature, some host systems might experience significant Oracle VirtualBox performance degradation.
По личному опыту и множеству дискуссий в интернете, тормозит везде.
В общем, с включенным Hyper-V VirtualBox становится практически нефункционален.
Честно говоря, не могу сказать про VMware, но есть основания полагать что там то же самое.
Нет, речь про WSL целиком, то есть в первую очередь про WSL2 как текущую актуальную версию.
В репозитории с исходниками WSL есть ссылка на связанную репу с исходниками ядра, распространяемого в составе WSL. Большинство документации, озаглавленной просто WSL упоминает возможность установки разных дистрибутивов. В общем, WSL это WSL2 если явно не указано иное.
Поэтому да, оно до сих пор требует Hyper-V (с другой стороны, а куда оно денется?) и конфликтует с установленными сторонними гипервизорами. Либо WSL, либо виртуалка, выбирайте что вам важнее. Впрочем выключить Hyper-V становится все сложнее с каждой новой версией ОС.
Примеры можно? Что-то мне сложно представить, как using-ами можно код испортить.
А примеры как испортили код отсутствием using там, где в этом нет явной на то необходимости? Сотый раз говорю, у алиасов конечно же есть применение. Иногда допустипо или даже надо их применять. Просто не надо пихать их там, где они лишь обфусцируют написанное.
Вообще вся дискуссия выглядит довольно сюрно:
std::unique_ptr<Shape> -- это ужас, прямо-таки признак профнепригодности. А вот ShapeUniquePtr -- это совсем другое дело!
Остается переименовать int в Signed, std::string в String и т. п. и вот тогда все станет просто и понятно, ведь
именованные типы (даже в виде алиасов) служат как дополнительный слой абстракции и скрывают лишние детали
Можно еще using namespace std полирнуть, потому что
уже из названия типа видно, с каким указателем типом мы имеем дело и это отнимает гораздо меньше усилий, чем читать бесконечные std::
Да-да, reductio ad absurdum, но я уже не знаю как еще реагировать.
и главное, если со временем потребуется заменить тип за ShapeUptr на какой-то другой, то имя ShapeUptr все равно остается на месте
Или вот это. Давайте просто втихаря подменим реализацию.
Это кстати прекрасная иллюстрация одной из причин большей когнитивной нагрузки от излишнего применения алиасов: всегда надо быть начеку. Даже если ты читал этот код вчера и запомнил что есть что, сегодня кто-нибудь мог все поменять.
Или вот это. Давайте просто спрячем эту жесть под коврик и сделаем вид что так и надо.
А что пользоваться этим невозможно, так кому какое дело.
Что любопытно, действительно можно вообразить такие ситуации, когда ваши аргументы будут оправданы. Стандартная библиотека вон полна алиасов, например. Но какое это имеет отношение к 95% тривиальнейших случаев по типу std::unique_ptr<Shape> в примере выше?
Что, конечно же, вас ничуточку не переубедит. Поэтому здесь мои полномочия видимо все, окончены =(.
Но код читается кратно больше, чем пишется. И когнитивная нагрузка - это про чтение, а не про написание.
Именно. И поэтому аргумент мол не хочется выписывать раз за разом полное имя -- плохой.
Здесь алиасы работают, как хорошее именование переменных
Именно. И поэтому сокращение имен или использование нестандартных наименований без существенной на то причины -- усложняет чтение.
Семантика владения и прочие детали важны при написании кода
И при попытке понять что происходит в данном фрагменте кода. Особенно когда неочевидно это оно специально так написано или случайно получилось и возможно тут ошибка.
Но опять-таки, не все алиасы плохие. Дискуссия началась с использования using ShapeUptr = std::unique_ptr<Shape>. Это, положа руку на ногу, просто бесполезная перестановка символов местами, которая выигрывает несколько символов ценой замены явного, всем и каждому понятного типа на локальную историю, которую надо будет найти и запомнить (и сразу же забыть, потому что в каждом случае она разная). Зачем? Просто потому что.
auto также скрывает тип, но повсеместен в современном C++. Хотя может вы из секты людей, которые всегда явно пишет тип переменных?
Фундаментальное отличие auto в том, что он скрывает тип в очень небольшом контексте. Грубо говоря вот видим объявление auto i = vec.begin(), и вот в пределах экрана эта переменная используется.
То же самое с локальным using в пределах области видимости.
Проблема с теми алиасами, которые определены где-то в совершенно другом месте и надо вспоминать/искать что это такое. IDE еще могут быстро подсказать, но при чтении/ревью например в web-интерфейсе это очень мешает.
Заметьте, что я не агитирую за полный отказ от using вообще. Только там, где без этого можно легко обойтись.
Алиасы значительно упрощают рефакторинг и позволяют избежать багов. Обобщенный код без алиасов я даже представлять не хочу.
Обобщенный алиас алиасу рознь. Одно дело using ElementType = T; в контейнере. И совсем другое это сокрытие семантики, как это часто происходит с указателями или многоэтажными контейнерами. Бездумное использование алиасов запросто может наоборот стать причиной неочевидной ошибки.
Но в реализациях функций и классов не вижу проблемы при грамотно выбранных именах.
Вот казалось бы, std::unique_ptr<Shape> -- куда уж лучше. Указатель, уникальный, из стандартной библиотеки. Но нет, это слишком просто.
Нюанс в том, что когда действительно неважно что это за тип, то как правило это будет typename T или auto =).
А вот что автор скрыл под Ptr -- unique, shared, QPointer, указатель из boost или вообще голый указатель -- это обычно существенно влияет на семантику владения, совместимость между типами и как с этим можно обращаться вообще помимо -> и *.
Да, внутри функции вам действительно часто все равно, что это за указатель. Ну так в названии переменной или поля тип и не указывается, shape и shape.
Нет. Вы сразу ошибаетесь. Все, что вы написали -- это ерунда.
Вы меня конечно извините, но это аргументация уровня "нет ты".
когда в проекте есть устоявшиеся правила именования указателей (вроде ShapeUptr, ShapeShptr), то уже из названия типа видно
Это можно отнести к упомянутому мной частному случаю, когда типы настолько общеупотребимы в проекте, что без их знания все равно никуда. Кроме того, если в проекте исторически сложилось использование таких сокращений, то бессмысленно спорить. Даже если используется какая-нибудь венгерская нотация, все равно придется писать как уже написано.
Закавыка в том, что все равно у каждого второго проекта будут свои собственные устоявшиеся правила. Вам может показаться что ShapreUptr это что-то совершенно очевидное, но это не так.
Особенно в сочетаниях типа std::shared_ptr<std::vector<std::unique_ptr<Shape>>>
По-моему это больше похоже на контр-пример.
Пользоваться такими типами очень тяжело и легко приводит к ошибкам, с алиасом или без. Если в коде постоянно нужно использовать и передавать что-то подобное, то вместо тяп-ляп спрятать имя под алиасом, по-хорошему надо задуматься о выделении соответствующей сущности в отдельный тип.
Потому что постоянное жонглирование вложенностью-разыменованием и безымянными полями абстрактных контейнеров это форменная жесть с какой стороны ни посмотри.
Имя, которое невыносимо печатать из-за его длины -- это чаще всего признак проблемы, которую надо решать не алиасом.
Ну и главное, хорошие привычки нужно вырабатывать сразу, на простых ученических задачках.
Как например использование emplace_back() вместо push_back() даже если в данном конкретном случае компилятор оптимизирует лишний move в ноль? =)
Но суть моей придирки к алиасам в том, что вы фактически производите небольшую обфускацию и называете это хорошей привычкой.
Спасибо, но вредные советы (а это очень вредный совет) идут в сад.
Ну так вы первый начали.
Любой алиас это сокрытие конкретного типа и небольшая, но дополнительная когнитивная нагрузка на удержание в памяти что это такое на самом деле и/или постоянные сверки то ли это, что ты думаешь.
Даже дюжина повторений в коде не стоит этого. Вы несколько раз экономите невероятные 10 символов, из которых половину все равно подставит IDE, а читаете это снова и снова и снова каждый раз, когда приходится вернуться к этому фрагменту кода.
Одно дело, если тип фундаментален для проекта и используется в нем повсеместно. Но в единичных и/или простых случаях использование всяких FooPtr, FooMap и прочих одному автору понятных типов только лишь потому что видите ли лень пару лишних клавиш нажать -- это вредная практика.
Претензия к использованию устаревших и не идиоматических конструкций. Как будто вы не очень хорошо знаете C++, но тогда возникает вопрос зачем вы пишете пример именно на нем?
В интернетах периодически можно видеть обсуждения а не добавить ли в C механизм defer? И там тоже половина воспринимает идею в штыки, мол не надо в наш простой и понятный C тащить всякие неявные defer, есть же goto.
И вот представляется мне как разработчики на Go смотрят на это и думают, вот чудные, такой простой, понятный и удобный механизм не хотят использовать. А потом переключаются на соседнюю вкладку и критикуют синтаксический сахар обработки ошибкок, мол не надо в наш простой и понятный Go тащить всякие неявные try, есть же if =).
На это смотрят разработчики например на Rust и думают, вот чудные, такой простой, понятный и удобный механизм не хотят использовать. А потом переключаются на соседнюю вкладку и...
Квантовая эффективность -- это процент фотонов, которые были преобразованы в электричество, от общего числа поглощенных фотонов.
Один большой пиксель некоторой площади поглотит и преобразует то же самое количество фотонов, что и несколько более мелких пикселей суммарно той же самой площади.
Поэтому в отрыве от контекста кажется ну вот же, один большой пиксель шумит меньше -- значит это лучше, а по факту общее количество информации и суммарный сигнал/шум всего изображения остаются одни и те же.
Но недостаток света и результирующий шум всего изображения целиком не коррелирует с размером пикселя. Если бы вместо 200 МП сенсора использовали 50 МП сенсор -- результат был бы точно тот же самый.
Причем в данном случае практически буквально. С учетом той оптики, которая используется в смартфонах (в первую очередь f-число) оптическая система модуля камеры с сенсором такого размера (порядка 1/1.4") оказывается диффракционно ограничена примерно 50 МП.
Я вам по секрету расскажу =) практически все изображения и видео (подавляющее большинство популярных форматов и кодеков) и по сей день это отдельные пространства яркости и цвета с пониженным разрешением (дискретизацией) цвета.
Это может быть несколько контринтуитивно, но при всех прочих равных размер пикселя играет мало роли.
Да, большой пиксель как будто бы менее шумный, но конечное изображение будет выглядеть по сути одинаково независимо от того, будет оно составлено из меньшего количества менее шумных пикселей или большего количества пропорционально более шумных пикселей.
Собственно это и позволяет производителям смартфонов творить такую лютую дичь, как использование 200 МП сенсора -- в итоге работать он будет плюс-минус так же, как и 24 МП сенсор того же размера. По той же причине полнокадровая камера высокого разрешения (например Sony A7RV с 61 МП матрицей) показывает такое же качество изображения, как и полнокадровая камера меньшего разрешения (например, Sony A7III с 24 МП матрицей) при существенно меньшем размере пикселя.
Потому что если самую чуточку упростить, качество всего изображения упирается в два фактора: количество проецируемого света (фотонный шум) и схемотехника сенсора (электронный шум). А размер пикселя дело десятое.
А для сенсоров одного технического поколения-исполнения все и вовсе упирается в количество света. Поэтому пытаются либо увеличить размер сенсора (чтобы впитать больше света при одинаковой светосиле объектива), либо увеличить светосилу объектива (чтобы спроецировать больше света при одинаковом размере сенсора), либо и то, и другое одновременно. Ну и еще иногда делают что-нибудь такое эдакое с самим сенсором, но это в последнее время редкость.
Тут есть нюанс: это мало подходит для съемки сцен, в которых присутствует движение, даже такое небольшое как колышащиеся на ветру ветки деревьев. Многие камеры имеют режим Pixel Shift и обычно он подходит для съемки только полностью статичных объектов.
VirtualBox через Hyper-V работает со скоростью черепахи, они даже иконку соответствующую при этом в трее рисуют.
Из документации к последней версии:
По личному опыту и множеству дискуссий в интернете, тормозит везде.
В общем, с включенным Hyper-V VirtualBox становится практически нефункционален.
Честно говоря, не могу сказать про VMware, но есть основания полагать что там то же самое.
Нет, речь про WSL целиком, то есть в первую очередь про WSL2 как текущую актуальную версию.
В репозитории с исходниками WSL есть ссылка на связанную репу с исходниками ядра, распространяемого в составе WSL. Большинство документации, озаглавленной просто WSL упоминает возможность установки разных дистрибутивов. В общем, WSL это WSL2 если явно не указано иное.
Поэтому да, оно до сих пор требует Hyper-V (с другой стороны, а куда оно денется?) и конфликтует с установленными сторонними гипервизорами. Либо WSL, либо виртуалка, выбирайте что вам важнее. Впрочем выключить Hyper-V становится все сложнее с каждой новой версией ОС.
И VirtualBox тоже, само собой =(.
Есть такая штука, называется "здравый смысл". Необязательно все доводить до абсурда =/.
К нынешнему моменту наверное 99% опенсурса хостятся на двух платформах: github и gitlab. Сложно найти разработчика, который с ними не сталкивался.
Я конечно догадался что вы не признали термин merge request, потому и написал мол это как pull request, только gitlab.
И разумеется это мало чем отличается от 2015, вот как будто непонятно откуда в моем комментарии взялся 2025.
Автор исходного комментария посетовал (справедливо) мол как можно так писать на C++ в 2025. А еще он сказал что не знает, что такое MR.
Я поиронизировал мол как можно в 2025 не знать что такое pull/merge request, особенно если приходится часто ревьють код.
А примеры как испортили код отсутствием using там, где в этом нет явной на то необходимости? Сотый раз говорю, у алиасов конечно же есть применение. Иногда допустипо или даже надо их применять. Просто не надо пихать их там, где они лишь обфусцируют написанное.
Вообще вся дискуссия выглядит довольно сюрно:
std::unique_ptr<Shape> -- это ужас, прямо-таки признак профнепригодности. А вот ShapeUniquePtr -- это совсем другое дело!
Остается переименовать int в Signed, std::string в String и т. п. и вот тогда все станет просто и понятно, ведь
Можно еще using namespace std полирнуть, потому что
Да-да, reductio ad absurdum, но я уже не знаю как еще реагировать.
Или вот это. Давайте просто втихаря подменим реализацию.
Это кстати прекрасная иллюстрация одной из причин большей когнитивной нагрузки от излишнего применения алиасов: всегда надо быть начеку. Даже если ты читал этот код вчера и запомнил что есть что, сегодня кто-нибудь мог все поменять.
Или вот это. Давайте просто спрячем эту жесть под коврик и сделаем вид что так и надо.
А что пользоваться этим невозможно, так кому какое дело.
Что любопытно, действительно можно вообразить такие ситуации, когда ваши аргументы будут оправданы. Стандартная библиотека вон полна алиасов, например. Но какое это имеет отношение к 95% тривиальнейших случаев по типу std::unique_ptr<Shape> в примере выше?
Что, конечно же, вас ничуточку не переубедит. Поэтому здесь мои полномочия видимо все, окончены =(.
Именно. И поэтому аргумент мол не хочется выписывать раз за разом полное имя -- плохой.
Именно. И поэтому сокращение имен или использование нестандартных наименований без существенной на то причины -- усложняет чтение.
И при попытке понять что происходит в данном фрагменте кода. Особенно когда неочевидно это оно специально так написано или случайно получилось и возможно тут ошибка.
Но опять-таки, не все алиасы плохие. Дискуссия началась с использования using ShapeUptr = std::unique_ptr<Shape>. Это, положа руку на ногу, просто бесполезная перестановка символов местами, которая выигрывает несколько символов ценой замены явного, всем и каждому понятного типа на локальную историю, которую надо будет найти и запомнить (и сразу же забыть, потому что в каждом случае она разная). Зачем? Просто потому что.
Фундаментальное отличие auto в том, что он скрывает тип в очень небольшом контексте. Грубо говоря вот видим объявление auto i = vec.begin(), и вот в пределах экрана эта переменная используется.
То же самое с локальным using в пределах области видимости.
Проблема с теми алиасами, которые определены где-то в совершенно другом месте и надо вспоминать/искать что это такое. IDE еще могут быстро подсказать, но при чтении/ревью например в web-интерфейсе это очень мешает.
Заметьте, что я не агитирую за полный отказ от using вообще. Только там, где без этого можно легко обойтись.
Обобщенный алиас алиасу рознь. Одно дело using ElementType = T; в контейнере. И совсем другое это сокрытие семантики, как это часто происходит с указателями или многоэтажными контейнерами. Бездумное использование алиасов запросто может наоборот стать причиной неочевидной ошибки.
Вот казалось бы, std::unique_ptr<Shape> -- куда уж лучше. Указатель, уникальный, из стандартной библиотеки. Но нет, это слишком просто.
Ну а я насмотрелся на тех, которые пихают typedef и using где надо и не надо.
Явное всегда лучше неявного.
Если у вас программисты пишут плохой код потому что они не используют using почем зря -- дело совершенно точно не в using.
Вот тут вынужден согласиться, в данном случае почем зря emplace приплел.
Ну значит возьмем B-сплайны. Какими кривыми аппроксимировать это детали реализации. В первом приближении можно вообще набором прямых обойтись.
Нюанс в том, что когда действительно неважно что это за тип, то как правило это будет typename T или auto =).
А вот что автор скрыл под Ptr -- unique, shared, QPointer, указатель из boost или вообще голый указатель -- это обычно существенно влияет на семантику владения, совместимость между типами и как с этим можно обращаться вообще помимо -> и *.
Да, внутри функции вам действительно часто все равно, что это за указатель. Ну так в названии переменной или поля тип и не указывается, shape и shape.
Вы меня конечно извините, но это аргументация уровня "нет ты".
Это можно отнести к упомянутому мной частному случаю, когда типы настолько общеупотребимы в проекте, что без их знания все равно никуда. Кроме того, если в проекте исторически сложилось использование таких сокращений, то бессмысленно спорить. Даже если используется какая-нибудь венгерская нотация, все равно придется писать как уже написано.
Закавыка в том, что все равно у каждого второго проекта будут свои собственные устоявшиеся правила. Вам может показаться что ShapreUptr это что-то совершенно очевидное, но это не так.
По-моему это больше похоже на контр-пример.
Пользоваться такими типами очень тяжело и легко приводит к ошибкам, с алиасом или без. Если в коде постоянно нужно использовать и передавать что-то подобное, то вместо тяп-ляп спрятать имя под алиасом, по-хорошему надо задуматься о выделении соответствующей сущности в отдельный тип.
Потому что постоянное жонглирование вложенностью-разыменованием и безымянными полями абстрактных контейнеров это форменная жесть с какой стороны ни посмотри.
Имя, которое невыносимо печатать из-за его длины -- это чаще всего признак проблемы, которую надо решать не алиасом.
Как например использование emplace_back() вместо push_back() даже если в данном конкретном случае компилятор оптимизирует лишний move в ноль? =)
Но суть моей придирки к алиасам в том, что вы фактически производите небольшую обфускацию и называете это хорошей привычкой.
Спойлер: в итоге не будет никаких Circle, Rectangle и прочих треугольников, останется только Shape с набором кривых, описывающих контур фигуры.
Ну так вы первый начали.
Любой алиас это сокрытие конкретного типа и небольшая, но дополнительная когнитивная нагрузка на удержание в памяти что это такое на самом деле и/или постоянные сверки то ли это, что ты думаешь.
Даже дюжина повторений в коде не стоит этого. Вы несколько раз экономите невероятные 10 символов, из которых половину все равно подставит IDE, а читаете это снова и снова и снова каждый раз, когда приходится вернуться к этому фрагменту кода.
Одно дело, если тип фундаментален для проекта и используется в нем повсеместно. Но в единичных и/или простых случаях использование всяких FooPtr, FooMap и прочих одному автору понятных типов только лишь потому что видите ли лень пару лишних клавиш нажать -- это вредная практика.
Использование алиасов почём зря (например в подобных тривиальных случаях) ухудшает читаемость кода. Не надо так.
Скорее наверное emplace_back()?
Это довольно иронично, что вы в 2025 не знаете что такое MR =). Подсказка: это как PR, только gitlab.
Претензия не к ООП или архитектуре.
Претензия к использованию устаревших и не идиоматических конструкций. Как будто вы не очень хорошо знаете C++, но тогда возникает вопрос зачем вы пишете пример именно на нем?
Судя по ближайшим планам основных дистрибутивов, X11 удалят из репозиториев ещё до того, как доделают Wayland.