Re[5]: offsetof() без UB
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 25.03.25 11:56
Оценка:
Здравствуйте, rg45, Вы писали:

R>то, что делаешь методом научного тыка, ты делаешь на свой страх и риск.


Да в программировании для открытых систем (а тут большинство только для таких и делает), внезапно, почти все делается на свой страх и риск.
Re[6]: offsetof() без UB
От: rg45 СССР  
Дата: 25.03.25 12:02
Оценка: :)
Здравствуйте, Евгений Музыченко, Вы писали:

R>>то, что делаешь методом научного тыка, ты делаешь на свой страх и риск.


ЕМ>Да в программировании для открытых систем (а тут большинство только для таких и делает), внезапно, почти все делается на свой страх и риск.


Большинство... Почти все... Какой съезд партии тебя делегировал, чтоб за всех расписаться?

Совсем уж примитивная демагогия: Ссылки на стереотипы и Выдача желаемого за действительное. Не разочаровывай меня.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 25.03.2025 12:09 rg45 . Предыдущая версия .
Re[6]: offsetof() без UB
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 25.03.25 15:10
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, rg45, Вы писали:


R>>то, что делаешь методом научного тыка, ты делаешь на свой страх и риск.


ЕМ>Да в программировании для открытых систем (а тут большинство только для таких и делает), внезапно, почти все делается на свой страх и риск.


Хм, почему?
Открытые системы — не значит, что нет стандартов.
The God is real, unless declared integer.
Re[7]: offsetof() без UB
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 25.03.25 17:15
Оценка: :)
Здравствуйте, netch80, Вы писали:

N>Открытые системы — не значит, что нет стандартов.


Во-первых, их достаточно мало на фоне общего разнообразия. Во-вторых, их соблюдение весьма опционально — тот же POSIX не в состоянии заставить каждого сисадмина поддерживать свою систему в полном соответствии со стандартом. В-третьих, даже при полном соблюдении всех стандартов остается вероятность аппаратных ошибок и ошибок окружения, которая в среднестатистической конфигурации достаточно велика. Поэтому смысл снижать вероятность неправильного поведения программы ниже некоторого разумного порога есть только для небольшого класса сверхнадежных программ, работающих только в сверхнадежных же системах.
Re[8]: offsetof() без UB
От: rg45 СССР  
Дата: 25.03.25 17:55
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Во-первых, их достаточно мало на фоне общего разнообразия.


Так никто вроде и не говорил, что их много. К чему это вообще?

ЕМ>Во-вторых, их соблюдение весьма опционально — тот же POSIX не в состоянии заставить каждого сисадмина поддерживать свою систему в полном соответствии со стандартом.


Ну разумеется, стандарты не могут никого заставить себя соблюдать.

ЕМ>В-третьих, даже при полном соблюдении всех стандартов остается вероятность аппаратных ошибок и ошибок окружения, которая в среднестатистической конфигурации достаточно велика. Поэтому смысл снижать вероятность неправильного поведения программы ниже некоторого разумного порога есть только для небольшого класса сверхнадежных программ, работающих только в сверхнадежных же системах.


Детский сад какой-то. "Зачем чистить зубы, если всё равно умрёшь".
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 25.03.2025 18:08 rg45 . Предыдущая версия . Еще …
Отредактировано 25.03.2025 18:07 rg45 . Предыдущая версия .
Re[9]: offsetof() без UB
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 25.03.25 18:49
Оценка:
Здравствуйте, rg45, Вы писали:

R>Детский сад какой-то. "Зачем чистить зубы, если всё равно умрёшь".


Детский сад — это регулярно посматривать вверх на случай, если с пролетающего самолета будет что-нибудь падать.
Re[10]: offsetof() без UB
От: rg45 СССР  
Дата: 25.03.25 19:02
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Детский сад — это регулярно посматривать вверх на случай, если с пролетающего самолета будет что-нибудь падать.


Ты сам-то понял свою метафору?
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: offsetof() без UB
От: rg45 СССР  
Дата: 26.03.25 12:31
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Говоря о "гарантиях", полезно понимать, что это отнюдь не следствия законов природы, а всего лишь утверждения, обещания. Они соблюдаются, пока их невыгодно нарушать. Для каждой гарантии есть вероятность ее нарушения, которую следует соотносить с вероятностями других событий, которые могут повлиять на работу программы.


Вот ты странный. В том-то и дело, что никто тебе ничего не обещает. Но ты, тем не менее, рассчитываешь на то, чего тебе никто не обещал. Так получается.
--
Справедливость выше закона. А человечность выше справедливости.
Re[2]: offsetof() без UB
От: Кодт Россия  
Дата: 26.03.25 17:36
Оценка:
Здравствуйте, Chorkov, Вы писали:

C>Проблема будет при наследовании не классов, содержащих виртуальные функции, от классов не содержащих виртуальных функций, с виртуальным наследованием,...

C>https://gcc.godbolt.org/z/vnT9vnasM

Так а в чём тут проблема? Да, здесь база с ненулевым смещением.
Тот же эффект можно достичь на обычном множественном наследовании.
struct AB { int a, b; };
struct V { void* vfptr; };
struct C : V, AB { int c; };

static_assert(offsetof(AB, b) == sizeof(int));
static_assert(offsetof(C, b) == sizeof(Z) + offsetof(AB, b));
Перекуём баги на фичи!
Re[2]: offsetof() без UB
От: Кодт Россия  
Дата: 26.03.25 17:43
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>offsetof использует хак с разыменовыванием нулевого указателя. И получается на виртуальном наследовании это может не работать. Можно попробовать самому реализовать что-то подобное на уже существующем объекте


Для этого этот объект надо создать. Как в данном примере.
А у него конструктор не тривиальный, и хорошо, если у него вообще есть дефолтный конструктор, чтоб создать эталонный объект, который не жалко измерять.
Перекуём баги на фичи!
Re[3]: offsetof() без UB
От: sergii.p  
Дата: 27.03.25 08:38
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Для этого этот объект надо создать. Как в данном примере.


да, надо. Не спорю даже, этот вариант менее юзабелен чем offsetof. Но если это нужно для парсинга, то обычно объект уже есть.
Re[4]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 08:41
Оценка:
Здравствуйте, sergii.p, Вы писали:

SP>Но если это нужно для парсинга, то обычно объект уже есть.


Lazy evaluation?

Есть ещё один минус в таком подходе — полученное значение уже не будет compile-time.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.03.2025 8:43 rg45 . Предыдущая версия .
Re[5]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 09:00
Оценка:
Здравствуйте, rg45, Вы писали:

R>Есть ещё один минус в таком подходе — полученное значение уже не будет compile-time.


https://godbolt.org/z/8847Mjd7b
Re[6]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 09:11
Оценка:
Здравствуйте, kov_serg, Вы писали:

R>>Есть ещё один минус в таком подходе — полученное значение уже не будет compile-time.


_>https://godbolt.org/z/8847Mjd7b


Ну и где тут "объект уже есть", о чём говорилось выше? Ты же просто предлагаешь альтернативную реализацию offsetof, не требующую наличия объекта. Просто вместо UB от использования нулевого указателя, у тебя UB от неправомерного использования reinterpret_cast, вот и всё. Так ещё и тонны кода навертел.
--
Справедливость выше закона. А человечность выше справедливости.
Re[7]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 09:17
Оценка: :)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, kov_serg, Вы писали:


R>>>Есть ещё один минус в таком подходе — полученное значение уже не будет compile-time.


_>>https://godbolt.org/z/8847Mjd7b


R>Ну и где тут "объект уже есть", о чём говорилось выше? Ты же просто предлагаешь альтернативную реализацию offsetof, не требующую наличия объекта. Просто вместо UB от использования нулевого указателя, у тебя UB от неправомерного использования reinterpret_cast, вот и всё. Так ещё и тонны кода навертел.


Зато оно constexpr
Re[8]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 09:20
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Зато оно constexpr


Такое "оно" у нас и так есть.
--
Справедливость выше закона. А человечность выше справедливости.
Re[3]: offsetof() без UB
От: Chorkov Россия  
Дата: 27.03.25 09:37
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, Chorkov, Вы писали:


C>>Проблема будет при наследовании не классов, содержащих виртуальные функции, от классов не содержащих виртуальных функций, с виртуальным наследованием,...

C>>https://gcc.godbolt.org/z/vnT9vnasM

К>Так а в чём тут проблема? Да, здесь база с ненулевым смещением.

К>Тот же эффект можно достичь на обычном множественном наследовании.
К>
К>struct AB { int a, b; };
К>struct V { void* vfptr; };
К>struct C : V, AB { int c; };

К>static_assert(offsetof(AB, b) == sizeof(int));
К>static_assert(offsetof(C, b) == sizeof(Z) + offsetof(AB, b));
К>


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

При этом смещение, которое суть число — не содержит информации от начала экземпляра какого класса оно отсчитано.

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

Второй вариант ИМХО предпочтительнее.
Re[9]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 09:38
Оценка:
Здравствуйте, rg45, Вы писали:

R>Такое "оно" у нас и так есть.


Да ладно?
#include <cstddef>
#include <iostream>

struct A {
    int a,a1;
    virtual ~A() {}
};

struct B : virtual A { int b; virtual void f1() {} };
struct C : virtual A { int c; virtual void f2() {} };
struct D : B,C { int d; };

#define myoffset(member) template<typename T> size_t offset_of_##member(const T& temp) { return (size_t)((char*)(&(temp.member)) - (char*)&temp); }

myoffset(d)

template<typename> struct struct_member_types;
template<typename T, typename F> struct struct_member_types<F T::*> {
  using struct_type = T;
  using member_type = F;
};
template<typename T> using struct_type_t = typename struct_member_types<T>::struct_type;
template<typename T> using member_type_t = typename struct_member_types<T>::member_type;

template<auto field> struct constexpr_field_offset {
  using T = struct_type_t<decltype(field)>;
  using F = member_type_t<decltype(field)>;
  static constexpr const char const_holder = 0;
  static constexpr const T& const_value = reinterpret_cast<const T&>(const_holder);
  static constexpr const F T::* const_field = field;
  static constexpr const char* base_addr = &reinterpret_cast<char const&>(const_value);
  static constexpr const char* field_addr = &reinterpret_cast<char const&>(const_value.*const_field);
  static constexpr const size_t offset = field_addr - base_addr;
};
template<auto field> inline constexpr std::size_t offset_of = constexpr_field_offset<field>::offset;

int main(int argc, char **argv) {
    enum { c1=offset_of<&D::d> }; // это "оно" constexpr
    //enum { c2=offset_of_d(D{}) }; // а это "оно" не constexpr
    int v2=offset_of_d(D{}); 
    std::cout<< c1 << " " << v2 << std::endl;
    return 0;
}

28 28
Re[10]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 09:52
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Да ладно?


Так а с чем ты сравниваешь? С какой-то ещё одной собственной поделкой?

offsetof из стандартной библиотеки — компайлтаймовый: http://coliru.stacked-crooked.com/a/c386229829fc15c7.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.03.2025 10:02 rg45 . Предыдущая версия .
Re[11]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 10:50
Оценка:
Здравствуйте, rg45, Вы писали:

R>offsetof из стандартной библиотеки — компайлтаймовый: http://coliru.stacked-crooked.com/a/c386229829fc15c7.


Мало того что из стандартной библиотеки он предварительно уматерит (warning: ‘offsetof’ within non-standard-layout type ‘D’ is conditionally-supported [-Winvalid-offsetof]).
И как его в шаблонах использовать такой стандартный? Например:
template<auto f1,auto f2>constexpr int rel_ofs() {
    return offset_of<f1> - offset_of<f2>;
}

А со стандартным то как это задумывалось?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.