Гипотетически, можно заставить исполняться нечто находящееся в стеке — так gcc в рамках расширения компилятора поступает в C для вложенных функций, вроде как. В таком случае функция уже не будет синглтоном, но во-первых это плюс уязвимость, а во-вторых техника эта вроде как тонкая, низкоуровневая и неприятная.
Если этот пример считать, то всё же функции можно сделать не синглтоном, просто это антипаттерн, который или для странного api, или для какой-то jit-компиляции (не совсем это) и применять.
Оверъюз темплейтов может быть хорош для каких-то библиотек, но вытаскивать их из этих самых библиотек хорошей идеей абсолютно не кажется.
Системы сборки — даже если и использовать какой-то vcpkg, условный boost там будет отставать на минорную версию, и так и с другими библиотеками. Нехорошо, что из-за отсутствия некого центрального репозитория и системы сборки, создатели библиотек по итогу всё кидают на произвол условного гитхаба.
Старый-добрый процедурный стиль мне нравится, но самодостаточным его не назову.
Был бы рад (когда уже наконец?) добавлению рефлексии: без неё грустно многие вещи зазря вручную писать (жаль, что пока без аттрибутов).
Отсутствие единой реализации стандарта — было бы легко на душе выбирать для себя что-то одно, но для библиотек это нездорово. Хотя приятно, что неопределённое поведение постепенно из стандарта стирается.
Мне со стороны кажется, что тогда уж странно, что нужен ломбок чтобы что-то там генерировать, а не на уровне языка, как в kotlin. Как минимум, все эти getValue() setValue(x) утомляют. Изобретение свойств в более поздних языках кажется действительно чем-то хорошим; по крайней мере для геттеров: для сеттеров ещё соглашусь, что написать setValue(...) будет нагляднее, что под капотом будет некая каша, но вот у геттеров обычно под капотом обычно чистенько и пустенько.
Генерация конструкторов — полезно и классно, но можно было и проще + для иерархий начинает работать довольно плохо. Но необходимость иметь пустой коструктор лишь чтобы отдать его на инициализацию значений через сеттеры в условный hibernate… ладно, это вина самого hibernate будет. Жаль, что record в язык добавлен довольно поздно…
Насчёт памяти: пожалуй, но если понадобится использовать closeable-поля будет немного неприятно вручную писать close для композирующего класса. К счастью, всё же это не часто нужно. В плюсах этой проблемы с деструкторами нет, да и в джаве, если finalize использовать, но тут он всё же не пахнет какой-то детерминированностью, да и вообще deprecated. Даже странно, что в lombok нет аннотации для такого (ну, кроме @Delegate, наверное… не уверен).
Ладно, немного извиняюсь, я тут написал о некоторых вещах, которые лично мне были неприятны, когда меня вынудили использовать джаву, но вне отношения ко мне они может и считаются нормальными. Но а так, всё же как человеку со стороны, мало знакомому с некой реальной работой на джаве и потому, возможно чего-то не знающему, хочется спросить: почему не один из "детей" джавы? Если нет желания терять кучу уже имеющихся библиотек и решений, чем плох какой-нибудь Kotlin? (хотя его немного трудно читать бывает, тут да, с этими гипервложенными угловыми скобками). Он вроде же как имеет всякое из lombok встроенное прямо в язык, null-safe, ну и синтаксическим сахаром подприправлен (хотя кому-то такое и минус).
А так, я люблю размещать всё в стеке👍 и как фанату стека мне всё же грустно от переиспользования объектов и оттого я всё же думаю, что модель памяти со сборщиком мусора заставляет слишком на себя положиться, что заставляет создавать объекты на 100500 довольно странных случаев, в котрых через стек было бы лучше. В этом плане C# со struct и Kotlin с value class были хоть как-то неплохи, но не скажу, что полноценно.
Ну, опять же, это куда больше моё раздражение, чем конструктив. Модель памяти C++ (пост-C++11) или раста мне всё же кажутся получше, если не требуется закидывать ссылки в кучу непонятных и неясных мест. Тогда да, наверное можно и замучиться.
Короче говоря, извиняюсь за то, что так подсел. В каком-то смысле, технологии навроде Spring мне, начавшему с плюсов, кажутся по-своему удивительными. Так что, наверное, вне всех странных норм, всё же джава по-своему может быть полезна, да и свой большой след в истории оставила.
Я не эксперт и статью не дочитал пока, но я бы на месте автора тут бы поставил какой-нибудь restrict на мутабельный указатель, просто иначе тут может убиваться дикая часть оптимизаций. Хотя лучше сравнить ибо точно не уверен. В общем, я предлагаю ещё и так глянуть, что будет и как соптимизируется:
Из-за того, что у меня нет опыта написания статей, многого не расскажу, но наверное посоветую делать небольшие напоминания в тексте, что есть что. Просто если информации много (а тут так), то отдельные функции и определения легко забыть, а возвращаться по тексту не хочется.
Возможно, опытный редактор подсказал бы получше и побольше полезных советов, но я не один из них, поэтому могу лишь как читатель говорить что-то, к сожалению.
Вообще, как будто интересно… Я глянул предложение о рефлексии и мне интересно немного: почему функции std::meta решили сделать отдельными функциями, а не методами std::meta::info? Хотя, учитывая, что в плюсах у базовых типов впринципе иное поведение, чем у производных, а данный как будто сделали таковым, чтобы разные компиляторы могли считать его таковым… Иначе, не знаю как-то, странное дизайнерское решение, мне кажется.
Насчёт байта: пусть эксперименты с размером это и хорошо, но слова "байт = 8 бит" так у всех в голове укоренились, что мало кто бы стал писать исходя из обратного. Хотя, возможно, я не знаю какие-то нишевые области? Ну, многие языки уже приняли данное высказывание как стандарт, в любом случае. Отчасти к сожалению, ибо стандартизация чего-то это как отрезать ноги (взамен на то, чтобы вас не догнали с плохими намерениями)) ).
Про контракты: такое как будто лучше работает только если изначально является фишкой языка. Иначе получится как с добавлением добавлением nullability в C#. Или штук вроде @NotNull в java — такой пример точнее. Вроде и окей, но как по мне не на уровне всего языка с принуждением вручную ставить if и отслеживанием локально допустимых значений такое будет так себе, лишь пускаться исключениями или абортами. Но тут уж без отдельного диалекта никак, наверное, как в том странном предложении о safe-c++ (сейчас не найду его, но где-то на хабре есть). Кстати, такое вроде какие-то языки реализовывали как свои "кор-механики", можете напомнить, какие? red: немного погуглив, нашёл лишь spark. В остальном, эта идея какая-то малоиспользуемая, хах. В любом случае, оставить нечто в декларации это хорошо, но, довериться лишь на то, что программист, статический анализ (тут у него возможностей мало), тестирование и т.д. что-то там заметит — это не то, чтобы полноценно. Или же поясните, как это должно работать?
constexpr не особо часто приходится использовать, поэтому многие особенности всё же не помню, да и вспомнить всё же как будто проще будет лишь в момент необходимости:)
К сожалению, маркер constexpr как обещание не очень работает: вполне себе можно функцию, никак не работающую в comp-time, пометить constexpr, с точки зрения стандарта это вроде нормально, но точно я не помню. Это сделано для тех случаев, когда при одних вводных, функция работает в constexpr-"режиме", а при других в рантайме.
Возможно, это разрешимо с помощью consteval, но уже не помню. Типа такого:
Вообще, тут как будто четвёртое состояние всё же нужно: когда x и y несравнимы. Конечно, конкретно классического сравнения это касается слабо, но всё же сравнивать nan с чем-то — по версии ieee754 дело такое себе.
Да и если считать, что "меньше" это некое иррефлекивное асимметричное транзитивное соотношение, "равно"… короче пропустим, эти малопонятные слова. Например, из похожего, операция стогого подмножества в качестве "меньше" и равенства множеств в качестве "равно", ну и т.д., то как бы не верно {1}⪋{2, 3}. Спекуляция, конечно, но для чего-то вроде перегрузки операторов чутка неудобно кажется. Впрочем, тогда уж, считая, что nan!=nan… странно всё это. Сойдёмся на том, что это пустое рассуждение.
Ну и сверху уже писали, но я повторюсь: метрика эффективности взята с воздуха. Тут уж лучше глянуть с точки зрения хранения или как-то ещё, но не пальцем в небо.
что насчёт оператора "->*", кстати? Я глянул: его можно спокойно вне класса перегрузить. И по общей логике подходит. Единственное, не превращать его использование в то, что в первой строчке, ибо приоритет у него чуть ниже, чем у "()", что не совсем интуитивно:
(obj_ptr ->* ptr) (param) //реальность использования указателей на метод
obj ->* extention(param) //ожидание или если писать как конвеер
Их относительно легко использовать, особенно если использовать литералы.
Ну, тут немного моей личной фантазии, но если бы в c++ были бы shared immutable-строки как во многих языках на уровне хотя бы библиотеки, это было бы довольно хорошим решением, ибо можно было бы на constexpr-уровне сделать что-то вроде ""sv, но с возможностью конкатенации и другими плюшками.
Ну а так, лучше всего всегда писать ""sv тли ""s по ситуации. Но вообще, проблема первого в том, что операции конкатенауии и подобного недоступны, а воорого в том, что он всегда аллоцирующий.
Можно, конечно, написать нечто вроде ""s + "..."sv + some_fun(), но это не совсем то.
Гипотетически, можно заставить исполняться нечто находящееся в стеке — так gcc в рамках расширения компилятора поступает в C для вложенных функций, вроде как. В таком случае функция уже не будет синглтоном, но во-первых это плюс уязвимость, а во-вторых техника эта вроде как тонкая, низкоуровневая и неприятная.
Если этот пример считать, то всё же функции можно сделать не синглтоном, просто это антипаттерн, который или для странного api, или для какой-то jit-компиляции (не совсем это) и применять.
В коде
LinuxApi::write
почему идёт каст в uintptr, а возвращается intptr?Как начавшему с плюсов, отчасти соглашусь.
Оверъюз темплейтов может быть хорош для каких-то библиотек, но вытаскивать их из этих самых библиотек хорошей идеей абсолютно не кажется.
Системы сборки — даже если и использовать какой-то vcpkg, условный boost там будет отставать на минорную версию, и так и с другими библиотеками. Нехорошо, что из-за отсутствия некого центрального репозитория и системы сборки, создатели библиотек по итогу всё кидают на произвол условного гитхаба.
Старый-добрый процедурный стиль мне нравится, но самодостаточным его не назову.
Был бы рад (когда уже наконец?) добавлению рефлексии: без неё грустно многие вещи зазря вручную писать (жаль, что пока без аттрибутов).
Отсутствие единой реализации стандарта — было бы легко на душе выбирать для себя что-то одно, но для библиотек это нездорово. Хотя приятно, что неопределённое поведение постепенно из стандарта стирается.
Каких-то фич или сахара немного не хватает.
Такое у меня ви́дение.
Мне со стороны кажется, что тогда уж странно, что нужен ломбок чтобы что-то там генерировать, а не на уровне языка, как в kotlin. Как минимум, все эти getValue() setValue(x) утомляют. Изобретение свойств в более поздних языках кажется действительно чем-то хорошим; по крайней мере для геттеров: для сеттеров ещё соглашусь, что написать setValue(...) будет нагляднее, что под капотом будет некая каша, но вот у геттеров обычно под капотом обычно чистенько и пустенько.
Генерация конструкторов — полезно и классно, но можно было и проще + для иерархий начинает работать довольно плохо. Но необходимость иметь пустой коструктор лишь чтобы отдать его на инициализацию значений через сеттеры в условный hibernate… ладно, это вина самого hibernate будет. Жаль, что record в язык добавлен довольно поздно…
Насчёт памяти: пожалуй, но если понадобится использовать closeable-поля будет немного неприятно вручную писать close для композирующего класса. К счастью, всё же это не часто нужно. В плюсах этой проблемы с деструкторами нет, да и в джаве, если finalize использовать, но тут он всё же не пахнет какой-то детерминированностью, да и вообще deprecated. Даже странно, что в lombok нет аннотации для такого (ну, кроме
@Delegate
, наверное… не уверен).Ладно, немного извиняюсь, я тут написал о некоторых вещах, которые лично мне были неприятны, когда меня вынудили использовать джаву, но вне отношения ко мне они может и считаются нормальными. Но а так, всё же как человеку со стороны, мало знакомому с некой реальной работой на джаве и потому, возможно чего-то не знающему, хочется спросить: почему не один из "детей" джавы? Если нет желания терять кучу уже имеющихся библиотек и решений, чем плох какой-нибудь Kotlin? (хотя его немного трудно читать бывает, тут да, с этими гипервложенными угловыми скобками). Он вроде же как имеет всякое из lombok встроенное прямо в язык, null-safe, ну и синтаксическим сахаром подприправлен (хотя кому-то такое и минус).
А так, я люблю размещать всё в стеке👍 и как фанату стека мне всё же грустно от переиспользования объектов и оттого я всё же думаю, что модель памяти со сборщиком мусора заставляет слишком на себя положиться, что заставляет создавать объекты на 100500 довольно странных случаев, в котрых через стек было бы лучше. В этом плане C# со
struct
и Kotlin сvalue class
были хоть как-то неплохи, но не скажу, что полноценно.Ну, опять же, это куда больше моё раздражение, чем конструктив. Модель памяти C++ (пост-C++11) или раста мне всё же кажутся получше, если не требуется закидывать ссылки в кучу непонятных и неясных мест. Тогда да, наверное можно и замучиться.
Короче говоря, извиняюсь за то, что так подсел. В каком-то смысле, технологии навроде Spring мне, начавшему с плюсов, кажутся по-своему удивительными. Так что, наверное, вне всех странных норм, всё же джава по-своему может быть полезна, да и свой большой след в истории оставила.
Я не эксперт и статью не дочитал пока, но я бы на месте автора тут бы поставил какой-нибудь
restrict
на мутабельный указатель, просто иначе тут может убиваться дикая часть оптимизаций. Хотя лучше сравнить ибо точно не уверен. В общем, я предлагаю ещё и так глянуть, что будет и как соптимизируется:если не против компиляторозависимости, то есть специальные #pragma под такое, вроде
Проблема ИИ в том, что его результаты могут быть намного менее детерминированы по сравнению с кодом.
Из-за того, что у меня нет опыта написания статей, многого не расскажу, но наверное посоветую делать небольшие напоминания в тексте, что есть что. Просто если информации много (а тут так), то отдельные функции и определения легко забыть, а возвращаться по тексту не хочется.
Возможно, опытный редактор подсказал бы получше и побольше полезных советов, но я не один из них, поэтому могу лишь как читатель говорить что-то, к сожалению.
Вот из F# пример, как там работает:
Но там как бы удобно, что есть оператор <|, который работает навроде обычной передачи в функцию, но с меньшим приоритетом самого оператора.
Я немного перегнул, но всё же думаю, что тут чем раньше, тем лучше. Но тут как будто впринципе всё лучше заранее планировать.
Как бы это сказать помягче…
Из фундаментальных предпосылок, было создано нечто весьма затруднительное для понимания. Я как-то потерял нить. Извиняюсь.
Могу ли я попросить прожёвывать чуть побольше, пожалуйста?
Вообще, как будто интересно… Я глянул предложение о рефлексии и мне интересно немного: почему функции
std::meta
решили сделать отдельными функциями, а не методамиstd::meta::info
? Хотя, учитывая, что в плюсах у базовых типов впринципе иное поведение, чем у производных, а данный как будто сделали таковым, чтобы разные компиляторы могли считать его таковым… Иначе, не знаю как-то, странное дизайнерское решение, мне кажется.Насчёт байта: пусть эксперименты с размером это и хорошо, но слова "байт = 8 бит" так у всех в голове укоренились, что мало кто бы стал писать исходя из обратного. Хотя, возможно, я не знаю какие-то нишевые области? Ну, многие языки уже приняли данное высказывание как стандарт, в любом случае. Отчасти к сожалению, ибо стандартизация чего-то это как отрезать ноги (взамен на то, чтобы вас не догнали с плохими намерениями)) ).
Про контракты: такое как будто лучше работает только если изначально является фишкой языка. Иначе получится как с добавлением добавлением nullability в C#. Или штук вроде
@NotNull
в java — такой пример точнее. Вроде и окей, но как по мне не на уровне всего языка с принуждением вручную ставить if и отслеживанием локально допустимых значений такое будет так себе, лишь пускаться исключениями или абортами. Но тут уж без отдельного диалекта никак, наверное, как в том странном предложении о safe-c++ (сейчас не найду его, но где-то на хабре есть). Кстати, такое вроде какие-то языки реализовывали как свои "кор-механики", можете напомнить, какие? red: немного погуглив, нашёл лишь spark. В остальном, эта идея какая-то малоиспользуемая, хах. В любом случае, оставить нечто в декларации это хорошо, но, довериться лишь на то, что программист, статический анализ (тут у него возможностей мало), тестирование и т.д. что-то там заметит — это не то, чтобы полноценно. Или же поясните, как это должно работать?про
if consteval
— в моменте перепутал, спасибо))constexpr
не особо часто приходится использовать, поэтому многие особенности всё же не помню, да и вспомнить всё же как будто проще будет лишь в момент необходимости:)К сожалению, маркер constexpr как обещание не очень работает: вполне себе можно функцию, никак не работающую в comp-time, пометить constexpr, с точки зрения стандарта это вроде нормально, но точно я не помню. Это сделано для тех случаев, когда при одних вводных, функция работает в constexpr-"режиме", а при других в рантайме.
Возможно, это разрешимо с помощью consteval, но уже не помню. Типа такого:
Ну, точно не знаю, наспех придумал.
Короче говоря, комитет очень сильно влюблён в свои возможности принимать самые странные решения.
Вообще, тут как будто четвёртое состояние всё же нужно: когда x и y несравнимы. Конечно, конкретно классического сравнения это касается слабо, но всё же сравнивать nan с чем-то — по версии ieee754 дело такое себе.
Да и если считать, что "меньше" это некое иррефлекивное асимметричное транзитивное соотношение, "равно"… короче пропустим, эти малопонятные слова. Например, из похожего, операция стогого подмножества в качестве "меньше" и равенства множеств в качестве "равно", ну и т.д., то как бы не верно {1}⪋{2, 3}. Спекуляция, конечно, но для чего-то вроде перегрузки операторов чутка неудобно кажется. Впрочем, тогда уж, считая, что nan!=nan… странно всё это. Сойдёмся на том, что это пустое рассуждение.
Ну и сверху уже писали, но я повторюсь: метрика эффективности взята с воздуха. Тут уж лучше глянуть с точки зрения хранения или как-то ещё, но не пальцем в небо.
что насчёт оператора "->*", кстати? Я глянул: его можно спокойно вне класса перегрузить. И по общей логике подходит. Единственное, не превращать его использование в то, что в первой строчке, ибо приоритет у него чуть ниже, чем у "()", что не совсем интуитивно:
Не знаю, о чём думали создатели стандарта
От человека, только учащегося создавать проекты — спасибо за статью. :)
Про doxygen — узнал впервые, и хорошо, что на раннем этапе). И за это отдельное спасибо.
нет, невозможно
откуда такое предположение?;)
Если честно, уровень абстракции растёт очень быстро. Общая суть понятна, но детали без достаточного опыта работы с подобным лишь взрывают мозг.
Странно, что U с -1 начинаются, конечно, какой-то dreamberd.) Это из-за изначально неудачно подобранного соглашения?
И ещё интересно, но уже просто для улучшения понимания:
Возьмём такой псевдокод на C++:
Это ведь S: (*–>*)–> * , верно? Ну, то есть "(*–>*)–> *" — это род S, да?
А если так, то для:
Род S это T –> *, верно?
Ещё из вопросов: можно пример "родов родов" , ибо что-то принадлежащее, если я правильно понимаю, U_2 или выше не знаю как представить. Типа такого:
, где "суперрод" у T это uint -> хз, где хз это не-generic суперрод?
Тяжело такое представлять, как и задачи, где подобное можно применить практически.
Ну, тут немного моей личной фантазии, но если бы в c++ были бы shared immutable-строки как во многих языках на уровне хотя бы библиотеки, это было бы довольно хорошим решением, ибо можно было бы на constexpr-уровне сделать что-то вроде ""sv, но с возможностью конкатенации и другими плюшками.
Ну а так, лучше всего всегда писать ""sv тли ""s по ситуации. Но вообще, проблема первого в том, что операции конкатенауии и подобного недоступны, а воорого в том, что он всегда аллоцирующий.
Можно, конечно, написать нечто вроде ""s + "..."sv + some_fun(), но это не совсем то.
Ну или, к примеру, условно:
Не откомпилируется