Портабельный аналог offsetof для указателя на член класса
Код:
VarType TClassType::* pvar;
Конкретнее сформулируйте проблему, что есть, что надо получить и ваши предположительные решения данной проблемы. И побольше кода.
Цитата: Ramon
Конкретнее сформулируйте проблему, что есть, что надо получить и ваши предположительные решения данной проблемы. И побольше кода.
Нужно получить смещение члена по pointer-to-member по аналогии с offsetof. Offsetof юзается так:
Код:
offset = offsetof(Vector2, x);
Но мне нужно получить тот же результат, но используя pointer-to-member:
Код:
float Vector2::* pm = &Vector2::x;
offset = ?;
offset = ?;
реинтерпретирование pm как числа оказалось непортабельным, также как и использование нулевого указателя по аналогии с offsetof.
Это все частности, что вам надо, глобальнее?
Цитата: Ramon
Это все частности, что вам надо, глобальнее?
именно это и надо, иначе придется переделывать много кода
PS: Надо видеть ситуацию целостно иначе вопрос останется без ответа.
Цитата: Ramon
Представьте контекст в котором будет юзаться оффсет как он выглядит сейчас и изменения которые вы внесли, иначе совершенно непонятно как и где соплями мазать.
PS: Надо видеть ситуацию целостно иначе вопрос останется без ответа.
PS: Надо видеть ситуацию целостно иначе вопрос останется без ответа.
Для своей ситуации я нашел другое решение. Но эта задача (определение смещения по pointer-to-member) для меня все еще представляет академический интерес.
Цитата: vAC
Для своей ситуации я нашел другое решение.
Что и требовалось доказать.
PS: Академический и практический интерес представляют конкретные задачи, а не сферические кони в вакууме.
Код:
struct Vector2
{
double x;
double y;
Vector2():x(0), y(0){}
};
using namespace std;
int main()
{
Vector2 *pv = 0;
cout << (int)&pv->x - (int)pv << ' ';
cout << (int)&pv->y - (int)pv << ' ';
double Vector2::* px = &Vector2::x;
double Vector2::* py = &Vector2::y;
cout << (int)&(pv->*px) - (int)pv << ' ';
cout << (int)&(pv->*py) - (int)pv << ' ';
return 0;
}
{
double x;
double y;
Vector2():x(0), y(0){}
};
using namespace std;
int main()
{
Vector2 *pv = 0;
cout << (int)&pv->x - (int)pv << ' ';
cout << (int)&pv->y - (int)pv << ' ';
double Vector2::* px = &Vector2::x;
double Vector2::* py = &Vector2::y;
cout << (int)&(pv->*px) - (int)pv << ' ';
cout << (int)&(pv->*py) - (int)pv << ' ';
return 0;
}
У меня выводит 0 8 0 8.
Что надо поменять, чтобы вышло то, что хочет автор темы?
Цитата: vAC
Компилятор PSP для первого члена возвращает в pvar значение 1, а не реальный 0.
А с чего вы взяли, что 0 - это реальное значение. То, что этот член описан у вас в классе первым, еще совсем не гарантирует, что его адрес будет равняться this.
извиняюсь, что ввел в заблуждение, видимо что-то проглючило.
Собственно есть например класс/структура
Код:
struct Vector {
float x, y;
};
float x, y;
};
нужно вычислить например смещение к y. С помощью offsetof делается так:
Код:
[SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]offset = offsetof[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]Vector[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2], y[/SIZE][SIZE=2]);
[/SIZE]
[/SIZE]
А если имеем указатель на член, то так:
Код:
float Vector::*pm = &Vector::y;
offset = (size_t) [SIZE=2]&(([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]Vector[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] *)(0)->*[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]pm[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]);
[/SIZE][SIZE=2]
offset = (size_t) [SIZE=2]&(([/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]Vector[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2] *)(0)->*[/SIZE][SIZE=2][COLOR=#010001][SIZE=2][COLOR=#010001]pm[/COLOR][/SIZE][/COLOR][/SIZE][SIZE=2]);
[/SIZE][SIZE=2]
[SIZE=2][/SIZE]
[SIZE=2]проблема была в том, что имеющийся код реинтерпретировал pm как само смещение. Для всех компиляторов это было верно, кроме PSP, он давал значение на 1 большее.
[/SIZE]
Код:
/* Offset of member MEMBER in a struct of type TYPE. */
#ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* The cast to "char &" below avoids problems with user-defined
"operator &", which can appear in a POD type. */
#define offsetof(TYPE, MEMBER) \
(__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */
#ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* The cast to "char &" below avoids problems with user-defined
"operator &", which can appear in a POD type. */
#define offsetof(TYPE, MEMBER) \
(__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */
Короче, опять я занимался изобретением велосипеда... Радует, что мой получился почти как стандартный.
Цитата: Kogrom
Решил таки посмотреть stddef.h из gcc:
Короче, опять я занимался изобретением велосипеда... Радует, что мой получился почти как стандартный.
Код:
/* Offset of member MEMBER in a struct of type TYPE. */
#ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* The cast to "char &" below avoids problems with user-defined
"operator &", which can appear in a POD type. */
#define offsetof(TYPE, MEMBER) \
(__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */
#ifndef __cplusplus
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#else
/* The cast to "char &" below avoids problems with user-defined
"operator &", which can appear in a POD type. */
#define offsetof(TYPE, MEMBER) \
(__offsetof__ (reinterpret_cast <size_t> \
(&reinterpret_cast <const volatile char &> \
(static_cast<TYPE *> (0)->MEMBER))))
#endif /* C++ */
Короче, опять я занимался изобретением велосипеда... Радует, что мой получился почти как стандартный.
*Поднял палец*