access? Его смысл соответствует тому, на что оно ссылается, http://eel.is/c++draft/defns.access, или же тут более широкий смысл, который затрагивает и манипуляции нескалярами? Меня смущает слово dynamic в описании, так как в соответствии с http://eel.is/c++draft/basic.memobj#intro.object-1 и http://eel.is/c++draft/defns.dynamic.type, http://eel.is/c++draft/defns.dynamic.type.prvalue, http://eel.is/c++draft/defns.static.type динамический тип может быть лишь у полиморфных объектов, то есть типа класса, не скаляра, и почему бы тогда просто не написать "the type".
И второй вопрос, говорит ли http://eel.is/c++draft/basic.lval#11.3, что скалярные/любые объекты, то есть память (даже без объектов http://eel.is/c++draft/basic.memobj#basic.life-6.4) можно инспектировать как байты?
Интроспектировать с какой целью?
Не имеет значения, интересует сама возможность
Я ещё почитаю...
Имеет значение для понимания твоего вопроса
Инспектировать = читать побайтно значения в памяти
Просто надо принять ванну, выпить чашечку кофе... А не просто с утра стандарт читать.
Это единственное время, когда я могу заниматься. Время кофе было часа 3 назад)
Так читай, что тебе мешает? Проблема будет когда ты что-то с прочитанным будешь делать. Да, при чтении нельзя выходить за границы адреса объекта, естественно
Да я про себя, я чуть позже ещё раз прочитаю.
1) access означает ровно то, что написано в defns.access. в том пункте выстраивается цепочка glvalue → object → value: доступ осуществляется к значению, а те три пункта описывают, как между собой должны соотноситься glvalue и объект. 2) ваш вопрос основывается на заведомо ложном утверждении «объекты, то есть память». объекты отделены от памяти, которая их хранит (storage). basic.lval#11.3 действительно дает вам возможность побайтово читать storage, но и только. если под памятью без объектов вы понимаете storage без объекта, то написать программу, которая будет из него побайтово читать, вы сможете, но она будет полагаться на неопределенное поведение согласно basic.life#7.1. если под памятью без объектов вы понимаете «просто» память, не storage, то не уверен, что вы вообще сможете написать такую программу, оставаясь в рамках ISO C++, потому конструкции языка С++ оперируют объектами (intro.object#1)
По поводу оперирования объектами убедили, и что без объетка обращаться нельзя, тогда я просто могу в хранилище создать массив unsigned char и считывать их, применяя в операции преобразования http://eel.is/c++draft/basic.indet#2, "отмывая". По поводу памяти и storage, memory == storage, так как http://eel.is/c++draft/basic.memobj#intro.memory-1 память есть непрерывная последовательность ОДНОГО или более байт, байт есть the fundamental STORAGE unit, значит storage == memory Но вот по поводу определения access, зачем всё-таки там http://eel.is/c++draft/expr#basic.lval-11.1 the dynamic type, ведь для scalar его dynamic type == static type
Ой, я не правильно сперва понял вторую часть, конечно же просто памяти быть не может, и если время жизни закончилось, у нас может остаться хранилище (а не просто память)
1) ничего вы не отмоете, потому что std::launder требует, чтобы объект существовал. basic.indet#2 все равно не позволяет вам полагаться на indeterminate values — лишь копировать их туда-сюда с сохранением неопределенности 2) не очень понимаю, к чему часть про storage и память. никто и не спорил, что storage находятся в памяти 3) dynamic type относится не скаляру внутри объекта, а к объекту, который этот скаляр содержит. перечитайте мой ответ, пожалуйста
Отмывка не про launder, а про использование неинициализированного значения объекта, что есть случаи, когда это не UB
расскажите, что ли, как вы собираетесь их использовать, раз хотите завести это под basic.indet#2
Но вот от перечитывания ответа про dynamic type понятнее не становится. Я же привел, что единственный контекст, когда говорят о динамическом типе, это динамический полиморфизм, который никоим образом не относится к scalar type
Объект может быть одного типа, а реально он другого типа (динамического)
потому что доступ происходит через glvalue. между glvalue и значением, о которых говорит определение access, есть еще объект. basic.lval#11 предъявляет требования именно к glvalue и объекту, которые могут быть куда сложнее, чем скаляр, в том числе и полиморфическими
Просто прошу, привидите мне пример, когда это имеет силу, за исключением указателя(ссылки) на базовый класс, указывающих на объект производного, иначе я не пойму И в контексте вашего ответа про access, объекты в данном вопросе не могут быть сложнее скаляра
то есть вы считаете, что этот пункт не имеет отношения к примеру ниже, потому что s сложнее, чем скаляр? struct A { int a{0}; int b{0}; }; A s; std::cout << s.a;
Строго по определению, здесь обращение к subobject int, как мне кажется, при помощи выражения типа int, а к объекту s нельзя access по определению, им manipulate
давайте тогда с такой стороны зайдем: если динамический тип объекта это его «истинный» тип, который не зависит от типа выражений, через которые с ним работают, то что вы понимаете под просто типом?
Все, благодарю, дошло. Благо работа связана с ходьбой, голова прояснилась. Данный список как раз представляет варианты статического типа, когда динамический суть истинный тип объекта в хранилище.
И получается, последний пункт говорит, что скалярные объекты можно считать как narrow символьные типы. Но более сложные объекты так считать не получится, такие как объекты типа класса. Я прав?
если вы имеете в виду basic.lval#11.3, то он позволяет осуществлять доступ к представлению в памяти любого объекта (basic.types.general#4)
Можно вопрос: ты язык так вот по стандарту ISO прямо учишь?
Но мы же выяснили, что access это обращение к объектам скалярного типа
мы обсуждали 11.1, про доступ через glvalue того же типа, что и динамический тип объекта а 11.3 позволяет получать доступ к значениям и через glvalue типа char/byte
Пару недель. Тут как-то сказали, что нельзя вызывать деструктор для автоматических/статических/тредовых переменных, ну меня в поисках истины и затянуло
Я про то, что в самом начале пункта написано "access"
Все можно, не все нужно)
мне кажется, мы кругами ходим в конструкциях языка С++, с помощью которых осуществляется доступ к значениям (которые могут быть лишь скалярного типа, как гласит примечание к определению access), используются glvalue, которые связаны с объектами, содержащими эти скалярные значения. basic.lval#11 описывает требования к этим glvalue в таких языковых конструкциях
Я кажется понял, access тут производится с точки зрения статического типа, который в последнем случае скалярный.
не уверен, что я вас понял, но на всякий случай сделаю еще один акцент: attempts to access the stored value of an object through a glvalue об этих «промежуточных» glvalue на «пути» access'а (в конце которого всегда скаляр) и идет речь
To access through a glvalue => to access through the char (the byte), так?
вы в своей замене не убрали glvalue, а просто опустили through a glvalue of type char, unsigned char or std::byte
Ну да, то есть access это не по взаимодействие с объектами, а про действия с glvalue, так?
access это про чтение или изменение значений (скаляров). а вот basic.lval#11 это про то, какими должны быть glvalue, когда вы их используете для доступа раз вы говорите про действия с glvalue, то я позволю себе напомнить, что glvalue, как и прочие *value, это разновидности выражений, а не объекты, как можно подумать из названия
Раз с этим разобрались, следующий вопрос. Access подразумевает ещё и модификацию, то есть таким образом возможно менять объекты на уровне байтов?
модификация является доступом, и только. те части стандарта, которые мы тут обсуждаем, никак не регулируют саму возможность читать или изменять значения скажем, изменять константные объекты нельзя. если мне не изменяет память, у скаляров другой принцип: можно менять побайтовое представление, если у типа есть значение, которое соответствует побайтовому представлению после изменения. для object type он тоже может быть справедлив, но ссылок не приведу
То есть обсуждаемый пункт говорит, что он запрещает некоторые вещи, а 3 пункта не запрещает (Но не верно, что он их разрешает). И чтение таким образом не запрещено стандартом, когда как модификация скорее всего запрещена где-то?
basic.life#11 регулирует, какие glvalue можно использовать при доступе к значениям. но ничего не говорит о том, можно ли это делать в принципе
Хорошо, и раз вы говорите про сериализации, читать через char можно любые объекты, пока они живы, верно?
Можно. Но только standard layout да и то ещё надо паковать структуры... Ну и получишь непереносимое нечто.
как правило, да. вот исключения, которые я сейчас вспомнил: 1) в нашей беседе всплывал basic.indet. не то чтобы там есть ограничения на чтение само по себе, но с прочитанными значениями можно очень мало чего делать. вывести их куда-то (для той же интроспекции) будет UB 2) у представления объектов помимо битов, определяющих значение, есть padding bits. их значение unspecified, то есть их можно прочитать и даже вывести, но стандарт не дает никаких гарантий на предмет того, какие значения вы увидите
Да, про indet я увидел, там после операций снова неопределенное получается. Тогда вот такой пример, что я с утра кидал, well-formed? Причем std::string можно заменить на любой тип, да? https://godbolt.org/z/7njh8n
насколько я могу судить, ответ утвердительный на оба вопроса. не очень понятно, правда, зачем вам static_cast<int> и почему бы не воспользоваться std::aligned_storage
Char'ы под hex выводятся как числа? Про вторую функцию я лишь пару дней назад узнать, ещё практики не было
не помню, кстати
а что если строка "Hello, World!" больше размера для SSO? :) зачем тогда такое нью?
Отвечаю, меня интересует возможность так делать с любым типом. Строку я для примера привел
можно с любым, почему нет то
только тут наверное надо явно деструктор вызвать ещё?
наверное, он все-таки ill-formed, потому что вы после вызова placement-new пользуетесь buffer так, будто этот объект еще существует, что неправда, потому что его storage был переиспользован. и критерии transparently replaceable тоже не удовлетворены. наверное, наиболее корректным будет читать байты в цикле через reinterpret_cast<std::byte*>(ptr)[i]
с другой стороны, это несколько идет вразрез с примером использования aligned_storage на cppref
Чего-то мне кажется это работать не будет
Соглашусь, только теперь новый вопрос возник. В описании прозрачной замены упоминаются "a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object", но здесь нет gvalue. Что вообще означают эти сущности в данном контексте? То, что программист вводит объявлением?
glvalue это подвид выражений скажем, buffer; это expression statement, где выражение является glvalue
указатели, ссылки и имена это то, из чего вы составляете выражения, которые потом делятся на lvalue, xvalue и prvalue в соответствии со стандартом либо я не понял ваш вопрос
Хорошо. Второе сообщение про использование массива после восстановления исходных объектов в нем. Как я описал, они не имеют ни имён, ни указателей, ни ссылок, поэтому прозрачная замена к ним не может относиться.
@ddvamp я могу ошибаться на этот счет, потому что оператор [] по определению формирует указатель и разыменовывает его. массива там и правда нет, но есть storage другого объекта, к байтам которого мы можем обращаться через такое lvalue-выражение
Обсуждают сегодня