Pull to refresh
3
0

Разработчик

Send message

Я думаю, имеется ввиду выкинуть iostreams на мороз именно в текущем виде. Просто ради примера, в Rust абстракции байтовых потоков ввода-вывода требуют реализации по одной функции на чтение и запись, соответственно. Это в самой базовой форме. В С++ тщательно ковыряться с буфером потока и, возможно, самим классом потока.

Тогда могли бы через string_view. И возвращать тоже часть string_view. Увы, много рассказывают про "безопасные практики" — при этом периодически добавляя способов отстрелить себе ногу.

Многомегабайтные заголовки сами по себе не такая большая беда. Компиляторы довольно давно научились это дело кешировать. Две гораздо большие проблемы — война макросов и свалка определений.


Война макросов, как можно догадаться — конфликт и наложение эффектов от макросов, определённых в разных заголовках.


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

Меня больше бомбануло от


struct to_chars_result
{
  char* ptr;
  std::errc ec;
};

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

Рейсер сам по себе уже давно не разрабатывается.
Для VSCode — RLS и соответственно поставить RLS как компонент. Единственная проблема — пока что для этого надо ставить найтли тулчейн. Сижу и пишу частично под виндовс, проблем в целом не имею.

Любопытно, спасибо. Вопрос в том, как сделать такое "слабое квантовое измерение". Посмотрим.

Если совсем коротко — линкуетесь с Qt динамически (фреймворк в отдельных DLL/SO) и творите что хотите. В своём коде конечно.

Уважаемый antoshkka, у вас случайно нет "человекочитаемого" описания текущего состояния по модулям — на каком уровне они существуют (грубо — единица трансляции или линковки), как предполагается существующий код с инклюдами приводить к модульному виду и т.п. Судя по https://habrahabr.ru/company/yandex/blog/336264/#comment_10449246, понимания, как оно должно быть, нет как минимум у меня.

Полигоны прошлый век. Только конвексные воксели!

Подозреваю, что этот и предыдущий комментарий — ответы на https://habrahabr.ru/company/technoserv/blog/339156/#comment_10449494


Проблема ЕМНИП в том, что как только вы измеряете состояние одной частицы из пары, и получаете какой-то параметр для обоих, запутанность "сыпется", и у вас на руках 2 отдельных частицы. Поэтому данное явление на данный момент считается неприменимым для передачи информации быстрее скорости света. Более знающие да поправят.

Скорость света — предельная скорость передачи любого взаимодействия, не только движения.
https://ru.wikipedia.org/wiki/%D0%A2%D0%B5%D0%BE%D1%80%D0%B8%D1%8F_%D0%BE%D1%82%D0%BD%D0%BE%D1%81%D0%B8%D1%82%D0%B5%D0%BB%D1%8C%D0%BD%D0%BE%D1%81%D1%82%D0%B8#.D0.A1.D0.BF.D0.B5.D1.86.D0.B8.D0.B0.D0.BB.D1.8C.D0.BD.D0.B0.D1.8F_.D1.82.D0.B5.D0.BE.D1.80.D0.B8.D1.8F_.D0.BE.D1.82.D0.BD.D0.BE.D1.81.D0.B8.D1.82.D0.B5.D0.BB.D1.8C.D0.BD.D0.BE.D1.81.D1.82.D0.B8


Предпоследний абзац


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

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

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

Да, придётся добавить к таким функциям export. Зато будет понятно, где что лежит. При описанном вами сценарии с модулем в 10К строчек, делённым на несколько файлов, придётся ещё выяснять где лежит каждый кусок — т.к. логическое имя модуля вообще никак не связано с его местоположением в исходниках.

Пример с обработкой ошибок просто самый наглядный. Во второй половине комментария описан чуть более сложный случай. Добавьте туда пункт 2.5:


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


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

Потому что это удобно. Неприятно работать с одним файлом на 10к строчек.

Эмм, просто поделить на несколько вложенных модулей? С указанным подходом это будет тривиально.

Вырожденный пример будет какой-то такой


// Note: both FirstError and SecondError implement 'error' interface
// and use some data from value when their respective Error() is called

// May return non-nil error, if code fails
func first(arg MyData) *FirstError { /* some code here */ }
// May also return non-nil error, if code fails
func second(arg MyData) *SecondError { /* some other code here */ }

func third(arg MyHugeData) error {
    if err := first(arg.DataField); err != nil {
        return err
    }
    return second(arg.DataField)
}

func fourth(arg MyHugeData) {
    if err := third(arg); err != nil {
        fmt.Println(err.Error())
    }
}

Такой код КМК вполне может случиться — "просто верни статус последней операции дальше по стеку". Во-первых, результат всегда будет трактоваться как неуспех. Во-вторых, при попытке узнать причину мы получим nil-pointer panic из по сути ниоткуда. Пример с обработкой ошибок КМК просто будет самый типичный. Я в своё время нарвался на такое поведение в другом контексте, подробностей уже не помню.
Но суть была именно такой:


  1. Есть несколько типов, приводимых к одному интерфейсу.
  2. Каждый из типов требует не-нулевой инстанс чтобы корректно реализовывать указанный интерфейс
  3. В некоем коде, допустим при передаче через канал, указатель на объект какого-либо из конкретных типов приводится к интерфейсу. При этом для канала nil pointer является абсолютно корректным положением вещей и обрабатывается на принимающей стороне как положено.
  4. На принимающей стороне не-нулевой указатель на интерфейс неожиданно оказывается очень даже нулевым, т.к. сам по себе vtable бесполезен. Результат — NPE где не ждали.

Мне в общем-то тоже понятно, почему так происходит. Мне даже понятно, для чего используется эта фича. Что мне, к сожалению, осталось непонятно — почему это разрешено в виде неявного преобразования. Как по мне, сильно повышает шансы наступить на грабли. Было бы в виде явного тайп каста, так что неявный приводит к fully nil interface pointer — вопросов бы не было. Впрочем, как реализовали так реализовали. Может в v2 поменяют. Или давно есть линт, о котором я не знаю.

Подскажите пожалуйста одну вещь. В своё время я задавал вопрос, почему существует такая вещь как not-so-nil interface pointers — ситуация, когда nil-указатель на переменную конкретного типа неявно приводится к указателю на интерфейс, который этот тип реализует. И, как результат, у нас получается fat pointer с nil data pointer и валидным vtable pointer. Следствие — nil pointer dereference в рантайме, где его не ждали. Но вопрос не в этом. Вопрос в том, что ответ тогда был "потому что в Go указатели, а не ссылки". Как раз этот ответ я и не понял.

Подскажите пожалуйста кто в курсе по поводу двух особенностей модулей:


Своя нотация именования


// <root>/src/Module1.cpp
module foo.bar;
// ...
// <root>/src/dir1/Module2.cpp
module foo;
import foo.bar;

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


// <root>/src/Module1.cpp
import "Dir1/Module2"; // See below
// some code goes here

// ...
// <root>/src/Dir1/Module2.cpp
import "std/vector";
// some code with exports goes here

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


Глобальный модуль


В черновике упомянут некий "глобальный модуль", в который входит весь код до декларации module. Этот двойной пассаж мне честно говоря не понятен. Единственное подозрение — необходимость куда-то деть содержимое файла до декларации модуля.


Я попытался спросить в общей гугл группе https://groups.google.com/a/isocpp.org/forum/?fromgroups#!topic/std-proposals/SdgWgJCR35s, но мне к сожалению так никто и не ответил.

Information

Rating
Does not participate
Location
Украина
Registered
Activity