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

_>И как его в шаблонах использовать такой стандартный? Например:

_>
_>template<auto f1,auto f2>constexpr int rel_ofs() {
_>    return offset_of<f1> - offset_of<f2>;
_>}
_>


Ну это ты уже пытаешься увести обсуждение в сторону. Ты название темы-то прочитай.

В этой теме не обсуждается удобен или не удобен для использования в шаблонах. Обсуждается, как обойти накладываемые им ограничения и не влететь на UB. Ты же заменяешь одно UB на другое и обосновываешь это тем, что это удобнее для использования в шаблонах
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.03.2025 11:17 rg45 . Предыдущая версия .
Re[13]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 11:14
Оценка:
Здравствуйте, rg45, Вы писали:


_>>И как его в шаблонах использовать такой стандартный? Например:

_>>
_>>template<auto f1,auto f2>constexpr int rel_ofs() {
_>>    return offset_of<f1> - offset_of<f2>;
_>>}
_>>


R>Ну это ты уже пытаешься увести обсуждение в сторону. Ты название темы-то прочитай.


Приведите пример где этот offset_of даёт неверный резульат. Тогда и поговорим.
Re[14]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 11:20
Оценка:
Здравствуйте, kov_serg, Вы писали:


_>Приведите пример где этот offset_of даёт неверный резульат. Тогда и поговорим.


Так ты сам уже привёл этот пример. То, что его результат совпадает с твоими ожиданиями, является лишь частным проявлением неопределённого поведения.
--
Справедливость выше закона. А человечность выше справедливости.
Re[15]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 11:51
Оценка:
Здравствуйте, rg45, Вы писали:

_>>Приведите пример где этот offset_of даёт неверный резульат. Тогда и поговорим.


R>Так ты сам уже привёл этот пример. То, что его результат совпадает с твоими ожиданиями, является лишь частным проявлением неопределённого поведения.


Я про то что если нет виртуальных наследований то всё ок.
struct A { int a; };
struct B : virtual A { int b; };

int main(int argc, char const *argv[]) {
    B b[1];
    int A:: *p1=&B::a; // + member reference
//    int B:: *p2=&B::a; // - virtual memeber reference (очередное c++ и3#$6$тво)
    int B:: *p3=&B::b; // + member reference
    return 0;
}
Re[16]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 11:56
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Я про то что если нет виртуальных наследований то всё ок.


Ну, если UB для тебя это всё ОК, то желаю удачи.

Только вот здесь
Автор: rg45
Дата: 27.03 11:41
мы как раз обсуждали варианты, как обойти UB. Так что немного не в тему ты вклинился.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.03.2025 11:58 rg45 . Предыдущая версия .
Re[17]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 12:06
Оценка: :)
Здравствуйте, rg45, Вы писали:

R>Ну, если UB для тебя это всё ОК, то желаю удачи.

Для меня UB это приемлемо, если всё работает как задумано. Проблема в современных компиляторах, для них UB это возможность сделать пакость, причем желательно неочевидную.

R>Только вот здесь
Автор: rg45
Дата: 27.03 11:41
мы как раз обсуждали варианты, как обойти UB. Так что немного не в тему ты вклинился.

Ничего не понял но очень интересно. В c++ нет единообразия везде костыли и подпорки, поэтому имеем то что имеем.
Re[18]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 12:22
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Для меня UB это приемлемо, если всё работает как задумано. Проблема в современных компиляторах, для них UB это возможность сделать пакость, причем желательно неочевидную.


Причем, обо всех "пакостях" тебя предупреждают заранее. Но ты считаешь для себя приемлемым игнорировать эти предупреждения. Ну так и кто тебе злобный Буратино.

R>>Только вот здесь
Автор: rg45
Дата: 27.03 11:41
мы как раз обсуждали варианты, как обойти UB. Так что немного не в тему ты вклинился.

_>Ничего не понял но очень интересно.

Какие именно слова вызыают затруднения с пониманием?

_>В c++ нет единообразия везде костыли и подпорки, поэтому имеем то что имеем.


И это закономерный итог — имеете то, что имеете.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.03.2025 12:22 rg45 . Предыдущая версия .
Re[19]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 13:04
Оценка:
Здравствуйте, rg45, Вы писали:


R>Какие именно слова вызыают затруднения с пониманием?

те что из букв

_>>В c++ нет единообразия везде костыли и подпорки, поэтому имеем то что имеем.

R>И это закономерный итог — имеете то, что имеете.
Да
#include <iostream>

struct A { int a; };
struct B : virtual A { int b; };
struct C : virtual A { int c; };
struct D : B,C { int d; };

template<class T> T* get_instance() { static T t[1]; return t; }
template<class T,auto m> size_t offset() {
    T *t=get_instance<T>(); return (char*)&(t->*m)-(char*)t;
}

int main(int argc,char **argv) {
    std::cout<< "b:" << offset<D,&D::b>() << std::endl;
    std::cout<< "c:" << offset<D,&D::c>() << std::endl;
    std::cout<< "d:" << offset<D,&D::d>() << std::endl;
    std::cout<< "a:" << offset<D,&D::a>() << std::endl;
    return 0;
}

b:8
c:24
d:28
a:32
Re[20]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 13:10
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>
_>#include <iostream>

_>struct A { int a; };
_>struct B : virtual A { int b; };
_>struct C : virtual A { int c; };
_>struct D : B,C { int d; };

_>template<class T> T* get_instance() { static T t[1]; return t; }
_>template<class T,auto m> size_t offset() {
_>    T *t=get_instance<T>(); return (char*)&(t->*m)-(char*)t;
_>}

_>int main(int argc,char **argv) {
_>    std::cout<< "b:" << offset<D,&D::b>() << std::endl;
_>    std::cout<< "c:" << offset<D,&D::c>() << std::endl;
_>    std::cout<< "d:" << offset<D,&D::d>() << std::endl;
_>    std::cout<< "a:" << offset<D,&D::a>() << std::endl;
_>    return 0;
_>}
_>


Ну вот, без UB, но компайл тайм сразу пошёл погулять лесом. И для классов без дефолтных конструкторов это уже не работает. И для "тяжёлых" классов применять это уже стрёмно. А вдруг, класс в дефолтном конструкторе нажимает на кнопку уничтожения Вселенной?

И что ты хочешь продемонстрировать этим примером?
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.03.2025 13:16 rg45 . Предыдущая версия . Еще …
Отредактировано 27.03.2025 13:13 rg45 . Предыдущая версия .
Re[21]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 13:23
Оценка:
Здравствуйте, rg45, Вы писали:

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


_>>
_>>#include <iostream>

_>>struct A { int a; };
_>>struct B : virtual A { int b; };
_>>struct C : virtual A { int c; };
_>>struct D : B,C { int d; };

_>>template<class T> T* get_instance() { static T t[1]; return t; }
_>>template<class T,auto m> size_t offset() {
_>>    T *t=get_instance<T>(); return (char*)&(t->*m)-(char*)t;
_>>}

_>>int main(int argc,char **argv) {
_>>    std::cout<< "b:" << offset<D,&D::b>() << std::endl;
_>>    std::cout<< "c:" << offset<D,&D::c>() << std::endl;
_>>    std::cout<< "d:" << offset<D,&D::d>() << std::endl;
_>>    std::cout<< "a:" << offset<D,&D::a>() << std::endl;
_>>    return 0;
_>>}
_>>


R>Ну вот, без UB, но компайл тайм сразу пошёл погулять лесом. И для классов без дефолтных конструкторов это уже не работает. И для "тяжёлых" классов применять это уже стрёмно. А вдруг, класс в дефолтном конструкторе нажимает на кнопку уничтожения Вселенной?


R>И что ты хочешь продемонстрировать этим примером?

То что в C++ нет указателя &D::a вместо используется &A::a. Вот нахрена так было делать?
Re[22]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 13:50
Оценка:
Здравствуйте, kov_serg, Вы писали:

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


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


_>>>
_>>>#include <iostream>

_>>>struct A { int a; };
_>>>struct B : virtual A { int b; };
_>>>struct C : virtual A { int c; };
_>>>struct D : B,C { int d; };

_>>>template<class T> T* get_instance() { static T t[1]; return t; }
_>>>template<class T,auto m> size_t offset() {
_>>>    T *t=get_instance<T>(); return (char*)&(t->*m)-(char*)t;
_>>>}

_>>>int main(int argc,char **argv) {
_>>>    std::cout<< "b:" << offset<D,&D::b>() << std::endl;
_>>>    std::cout<< "c:" << offset<D,&D::c>() << std::endl;
_>>>    std::cout<< "d:" << offset<D,&D::d>() << std::endl;
_>>>    std::cout<< "a:" << offset<D,&D::a>() << std::endl;
_>>>    return 0;
_>>>}
_>>>


R>>И что ты хочешь продемонстрировать этим примером?

_>То что в C++ нет указателя &D::a вместо используется &A::a. Вот нахрена так было делать?

Ну потому что поле "a" является членом класса A. И выражение &D::a имеет тип указателя на член класса А. И указатель на член класса A без проблем может быть использован с объектом класса D, как с наследником класса A. А почему должно быть по-другому?

И вообще, какую связь ты видишь между этими вопросами и данной темой?
--
Справедливость выше закона. А человечность выше справедливости.
Re[23]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 13:57
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ну потому что поле "a" является членом класса A. И выражение &D::a имеет тип указателя на член класса А. И указатель на член класса A без проблем может быть использован с объектом класса D, как с наследником класса A. А почему должно быть по-другому?

Согласен, в c++ если можно сделать через ж... не единообразно то делают именно так.

R>И вообще, какую связь ты видишь между этими вопросами и данной темой?

Можно заранее (precompile) заготовить смещений вот где... зато будет constexpr.
struct A { int a; };
struct B : virtual A { int b; };
struct C : virtual A { int c; };
struct D : B,C { int d; };

template<class C,auto>struct Info;
template<>struct Info<A,&A::a> { enum { ofs=101 }; };
template<>struct Info<B,&B::a> { enum { ofs=102 }; };
template<>struct Info<B,&B::b> { enum { ofs=103 }; };
template<>struct Info<C,&C::a> { enum { ofs=104 }; };
template<>struct Info<C,&C::c> { enum { ofs=105 }; };
template<>struct Info<D,&D::a> { enum { ofs=106 }; };
template<>struct Info<D,&D::b> { enum { ofs=107 }; };
template<>struct Info<D,&D::c> { enum { ofs=108 }; };
template<>struct Info<D,&D::d> { enum { ofs=109 }; };

int main(int argc, char **argv) {
    enum { x=Info<D,&D::a>::ofs };
    return 0;
}
Отредактировано 27.03.2025 13:59 kov_serg . Предыдущая версия .
Re[24]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 14:29
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Согласен, в c++ если можно сделать через ж... не единообразно то делают именно так.


Пора уже отдельный форум создавать — "сердитых на С++". Модераторы быстро найдутся, я думаю.

R>>И вообще, какую связь ты видишь между этими вопросами и данной темой?

_>Можно заранее (precompile) заготовить смещений вот где... зато будет constexpr.

Ну это уже чтоб точно "через ж..."
--
Справедливость выше закона. А человечность выше справедливости.
Re[24]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 14:50
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>
_>struct A { int a; };
_>struct B : virtual A { int b; };
_>struct C : virtual A { int c; };
_>struct D : B,C { int d; };
_>


R>>Ну потому что поле "a" является членом класса A. И выражение &D::a имеет тип указателя на член класса А. И указатель на член класса A без проблем может быть использован с объектом класса D, как с наследником класса A. А почему должно быть по-другому?


_>Согласен, в c++ если можно сделать через ж... не единообразно то делают именно так.


Давай порассуждаем?

Легально ли такое использование, или его следует запретить?

    D d{};
    auto m = &A::a;

    std::cout << d.*m << std::endl;
--
Справедливость выше закона. А человечность выше справедливости.
Re[25]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 15:41
Оценка:
Здравствуйте, rg45, Вы писали:

R>Давай порассуждаем?

R>Легально ли такое использование, или его следует запретить?

R>
R>    D d{};
R>    auto m = &A::a;

R>    std::cout << d.*m << std::endl;
R>


Уже позно запрещать. Не нужно было вводить указатели на неведомую фигню.
У вас есть указатель на typedef? Тут примерно тоже самое. Сами себе создали проблемы и потом в лучщих традициях: породили новую сущность, породили методы работы с ней, но они не стыкуются с уже имеющимися,а и так сойдет.
struct A { int x[2]; };
struct B { A a[2]; };

Вот как записать указатель на поле B::a[1].x[1]. Обычного смещения относительно B было бы достаточно.
struct A { int *x; };
struct B { A *a; };

А вот для такого указателя на поле B::a[1].x[1]. Уже было бы достаточно ввести метод получения адреса, собственно и указатель бы был указателем на этот метод. Но нет это слишком просто.
Re[26]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 15:58
Оценка:
Здравствуйте, kov_serg, Вы писали:

R>>
R>>    D d{};
R>>    auto m = &A::a;

R>>    std::cout << d.*m << std::endl;
R>>


_>Уже позно запрещать. Не нужно было вводить указатели на неведомую фигню.

_>У вас есть указатель на typedef? Тут примерно тоже самое. Сами себе создали проблемы и потом в лучщих традициях: породили новую сущность, породили методы работы с ней, но они не стыкуются с уже имеющимися,а и так сойдет.

Чё-то эмоции через край, а на вопрос так и не ответил. Допустимо такое использование указателя на член, или нет? С твоей точки зрения, разумеется. Желательно с обоснованием.
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 27.03.2025 15:59 rg45 . Предыдущая версия .
Re[27]: offsetof() без UB
От: kov_serg Россия  
Дата: 27.03.25 16:40
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>
R>>>    D d{};
R>>>    auto m = &A::a;

R>>>    std::cout << d.*m << std::endl;
R>>>


_>>Уже позно запрещать. Не нужно было вводить указатели на неведомую фигню.

_>>У вас есть указатель на typedef? Тут примерно тоже самое. Сами себе создали проблемы и потом в лучщих традициях: породили новую сущность, породили методы работы с ней, но они не стыкуются с уже имеющимися,а и так сойдет.

R>Чё-то эмоции через край, а на вопрос так и не ответил. Допустимо такое использование указателя на член, или нет? С твоей точки зрения, разумеется. Желательно с обоснованием.


Да допустимо. При условии что тип d приводится к A а потом применяется указатель на поле класса A.
Re[28]: offsetof() без UB
От: rg45 СССР  
Дата: 27.03.25 17:06
Оценка:
Здравствуйте, kov_serg, Вы писали:

R>>Чё-то эмоции через край, а на вопрос так и не ответил. Допустимо такое использование указателя на член, или нет? С твоей точки зрения, разумеется. Желательно с обоснованием.


_>Да допустимо. При условии что тип d приводится к A а потом применяется указатель на поле класса A.


Не получается у меня что-то цепочка рассуждений, которая могла бы тебя переубедить. Я ещё подумаю.
--
Справедливость выше закона. А человечность выше справедливости.
Re[29]: offsetof() без UB
От: kov_serg Россия  
Дата: 28.03.25 12:23
Оценка:
Здравствуйте, rg45, Вы писали:

_>>Да допустимо. При условии что тип d приводится к A а потом применяется указатель на поле класса A.

R>Не получается у меня что-то цепочка рассуждений, которая могла бы тебя переубедить. Я ещё подумаю.

Пока думаешь. Я говорю примерно про такое
template<class> struct struct_member_types;
template<class T, class F> struct struct_member_types<F T::*> {
    using struct_t=T;
    using member_t=F;
};
template<class T>using struct_type_t=typename struct_member_types<T>::struct_t;
template<class T>using member_type_t=typename struct_member_types<T>::member_t;

template<auto field> struct fptr {
    using T = struct_type_t<decltype(field)>;
    using F = member_type_t<decltype(field)>;
    typedef F* (*type)(T*);
    static F* value(T* t) { return &(t->*field); }
};
template<auto m> inline constexpr typename fptr<m>::type ptr_to = fptr<m>::value;

//------------------------------------------------------------------------------

#include <stdio.h>
struct A { int a=101; };
struct B : virtual A { int b=102; };
struct C : virtual A { int c=103; };
struct D : B,C { int d=104; };

int main(int argc, char **argv) {
    D d[1];    
    auto p=ptr_to<&D::a>;
    printf("p=%p, *p=%d\n",p,*p(d));
    return 0;
}
p=0x40082f, *p=101
Re[30]: offsetof() без UB
От: rg45 СССР  
Дата: 28.03.25 13:06
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>Пока думаешь. Я говорю примерно про такое


Да идею-то я понял. Я не понимаю, каким образом тебе мешает то, что выражение &D::a имеет тип int A::*. Что для тебя изменилось бы, если бы тип был int D:*?
--
Справедливость выше закона. А человечность выше справедливости.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.