alignas(A) char data[sizeof(A)];
A* a = std::launder(reinterpret_cast<A*>(data));
Если A не POD тип? Если он наследуется от какого-то Base который имеет свои поля, который наследуется от некоего IAbstract у которого есть виртуальные методы реализуемые в A. Какие могут быть проблемы в c++17?
Доступ к приватным членам возможен только в контексте, где они видны компилятору , то есть внутри области, доступной на этапе компиляции. Попытка применить этот механизм к чужому классу без полного определения приведёт к ошибке компиляции — это гарантирует отсутствие произвольного доступа.
А я не понял как это работает. Если специализация идет не изнутри класса, то разве взятие адреса приватной переменной доступно? Адрес берется для инстанцирования шаблона, но в начале статьи ведь упоминалось, что нельзя взять адрес приватной переменной.
Шаблоны в C++ инстанцируются на этапе компиляции, и если специализация шаблона происходит в контексте, где приватный член доступен (например, внутри класса или через friend), то компилятор разрешит взять его адрес
class Foo{
private:
int a;
int b;
std::string& c;
};
Вообще я сам игрался с указателями на поля члены, делал на этом сериализацию. Для меня стали проблемой обращение к полям ссылкам и базовому классу. Код есть тут (с++17): https://github.com/aethernetio/aether-client-cpp/blob/main/aether/reflect/reflect.h Много пришлось подмазать макросами. Ну и в моем случае необходимость менять класс это фича, а не проблема.
Подумал было, что это уже должно работать в стандартном `std::tuple`, но как оказалось оно implementation defined. Плюс для msvc EBO оказывается нужно включать специально. Пример https://godbolt.org/z/dhEGfqnbz
У меня вопрос про [[no_unique_address]] А нет ли в компиляторах реализации своих кастомных атрибутов для до c++20 эпохи, так чтобы я мог наделать макросов и использовать [[no_unique_address]] фичу в c++17?
Про область видимости не совсем так. Обратите внимание https://godbolt.org/z/YTM1Kzq8r class X и Y объявляю внутри Foo, но X в той же области видимости что и Foo, а Y в области видимости внутри Foo.
С другой стороны, такая оценка нужна ровно в двух случаях: либо если вы собираетесь сделать дамп в памяти и хотите понять, сколько её надо резервировать, либо если вам надо строить внутренние таблицы релокации внутри такого дампа.
Ну звучит как достаточно важная оптимизация, но потенциально время самого GetBufLen может ее нивелировать.
У меня вопрос возник по поводу функций GetBufLen и SkipToEnd. В общем случае ведь, чтобы понять размер буфера требуемый для хранения структуры или пропустить ее в общем буфере. Нужно пройтись вглубь по всей структуре, разве это не будет равносильно по коду и времени сериализации/десериализации?
Пример есть класс, в котором вектор каких-то объектов.
Чтобы узнать размер буфера требуемого для хранения объекта этого класса, нужно узнать размер вектор, который известен, только в рантайме, и посетить каждый елемент этого вектора, так как внутри тоже могут быть динамические объекты. При пропуске, нужно прочитать из буфера размер вектора, затем прочитать каждый элемент, потому как из-за динамических объектов внутри, каждый элемент может быть разного размера и сколько пропускать не понятно.
Дополнительно про упакованные числа. Чтобы понять сколько байт нужно пропустить для числа в буфере, его ведь тоже нужно прочитать сначала?
Ну как зачем? Просто опытом поделится, вдруг кому-то будет полезно. Оно же тут не толкается, считаю пусть будет yet another статья или библиотека, чем не будет.
Вектор имеет размер и емкость. Тут речь про статическкую емкость, а размер как раз может меняться. Для std::vector ближайшим аналогом будет, если вы изначальное сделаете reserve и при добавлении элементов сами будете следить чтобы size() не превышал capacity(). Но std::vector память выделит в куче.
Здорово что тут получилось избавиться от аллокации. Но главный минус этой реализации, пользователю требуется подумать о времени жизни объектов. Если расширить функционал до использования с лямбдами, то станет очевидно, что такая реализация не так широко применима. Сам сейчас экспериментирую с разными подходами по теме.
Статья то не про ассемблер, а про то как устроен машинный код.
Да нет, там в оригинале прямо написано
std::string
. То есть проблема не в переводе, а в первоисточнике.не работает
У меня вопрос про конструкцию
Если
A
не POD тип? Если он наследуется от какого-тоBase
который имеет свои поля, который наследуется от некоегоIAbstract
у которого есть виртуальные методы реализуемые вA
. Какие могут быть проблемы в c++17?А я не понял как это работает. Если специализация идет не изнутри класса, то разве взятие адреса приватной переменной доступно? Адрес берется для инстанцирования шаблона, но в начале статьи ведь упоминалось, что нельзя взять адрес приватной переменной.
В коде я не вижу ни "внутри класса" ни "friend".
А вот такое оно сможет переварить?
Вообще я сам игрался с указателями на поля члены, делал на этом сериализацию. Для меня стали проблемой обращение к полям ссылкам и базовому классу.
Код есть тут (с++17):
https://github.com/aethernetio/aether-client-cpp/blob/main/aether/reflect/reflect.h
Много пришлось подмазать макросами. Ну и в моем случае необходимость менять класс это фича, а не проблема.
Подумал было, что это уже должно работать в стандартном `std::tuple`, но как оказалось оно implementation defined. Плюс для msvc EBO оказывается нужно включать специально.
Пример https://godbolt.org/z/dhEGfqnbz
А статья есть про это?
У меня вопрос про [[no_unique_address]]
А нет ли в компиляторах реализации своих кастомных атрибутов для до c++20 эпохи, так чтобы я мог наделать макросов и использовать [[no_unique_address]] фичу в c++17?
https://godbolt.org/z/Mb57YsMjc странно. Тут работает.
https://godbolt.org/z/Eh53TGc5e это и аргументами функции работает
Про область видимости не совсем так.
Обратите внимание https://godbolt.org/z/YTM1Kzq8r
class X и Y объявляю внутри Foo, но X в той же области видимости что и Foo, а Y в области видимости внутри Foo.
Сам когда-то увидел в каком-то виде с cppcon. Не мог найти примеры и как это называется. Пришлось чатгпт мучать.
Есть еще вот такая штука
https://stackoverflow.com/questions/37744047/class-declaration-inside-function-parameter-list?utm_source=chatgpt.com
И можно например написать вот так
Ну звучит как достаточно важная оптимизация, но потенциально время самого GetBufLen может ее нивелировать.
У меня вопрос возник по поводу функций GetBufLen и SkipToEnd. В общем случае ведь, чтобы понять размер буфера требуемый для хранения структуры или пропустить ее в общем буфере. Нужно пройтись вглубь по всей структуре, разве это не будет равносильно по коду и времени сериализации/десериализации?
Пример есть класс, в котором вектор каких-то объектов.
Чтобы узнать размер буфера требуемого для хранения объекта этого класса, нужно узнать размер вектор, который известен, только в рантайме, и посетить каждый елемент этого вектора, так как внутри тоже могут быть динамические объекты.
При пропуске, нужно прочитать из буфера размер вектора, затем прочитать каждый элемент, потому как из-за динамических объектов внутри, каждый элемент может быть разного размера и сколько пропускать не понятно.
Дополнительно про упакованные числа. Чтобы понять сколько байт нужно пропустить для числа в буфере, его ведь тоже нужно прочитать сначала?
Ну как зачем? Просто опытом поделится, вдруг кому-то будет полезно. Оно же тут не толкается, считаю пусть будет yet another статья или библиотека, чем не будет.
Вектор имеет размер и емкость. Тут речь про статическкую емкость, а размер как раз может меняться. Для std::vector ближайшим аналогом будет, если вы изначальное сделаете reserve и при добавлении элементов сами будете следить чтобы size() не превышал capacity(). Но std::vector память выделит в куче.
Ну например если мы знаем что элементов может быть не больше чем N, но не знаем сколько именно, и динамические аллокации делать не хочется.
Здорово что тут получилось избавиться от аллокации. Но главный минус этой реализации, пользователю требуется подумать о времени жизни объектов. Если расширить функционал до использования с лямбдами, то станет очевидно, что такая реализация не так широко применима.
Сам сейчас экспериментирую с разными подходами по теме.