Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> property в c++ 
:(
    Опции темы
Alca
Дата 22.8.2011, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3993
Регистрация: 14.6.2006

Репутация: 7
Всего: 50



Было бы неплохо убрать PROPERTY_BEGIN и PROPERTY_END:

Код

class Tclass3 {
    int FArray[2];
    static int GetArray(Tclass3* This, int Index) {return This->FArray[Index];}
    static int SetArray(Tclass3* This, int Value, int Index) {return This->FArray[Index] = Value;}
public:
        PROPERTY_IGS(Tclass3, int, GetArray, SetArray) Val3;
} t;


Это сообщение отредактировал(а) Alca - 22.8.2011, 12:09


--------------------
PM WWW ICQ Skype Jabber   Вверх
Ivan.
Дата 22.8.2011, 12:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Цитата(Alca @  22.8.2011,  12:09 Найти цитируемый пост)
Было бы неплохо убрать PROPERTY_BEGIN и PROPERTY_END:

не получается по следующим причинам:
1. пустая структура во многих компиляторах равна 1 байту. (100 пропертей займет 100 байт в классе). для этого все проперти объединены в union.
2. нельзя получить относительный адрес объекта внутри объявления этого объекта. для этого в начало union-на помещена структура с именем __PROP, по которой определяется смещение родителя от проперти.

Добавлено через 1 минуту и 30 секунд
еще ни как не могу вспомнить флаг компилятора позволяющий преобразовывать указатель метода к void*, чтобы уйти от статических мутаторов


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
bsa
Дата 22.8.2011, 12:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(Ivan. @  22.8.2011,  12:31 Найти цитируемый пост)
еще ни как не могу вспомнить флаг компилятора позволяющий преобразовывать указатель метода к void*

Размер указателя на метод класса может быть большего размера, чем указатель на данные.
PM   Вверх
Ivan.
Дата 22.8.2011, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Цитата(bsa @  22.8.2011,  12:46 Найти цитируемый пост)
Размер указателя на метод класса может быть большего размера, чем указатель на данные.

да, я понимаю. по этому такой флаг есть не во всех архитектурах. в билдере это не актуально, так как там есть настоящий проперти, в IAR_ARM указатель на метод равен 8 байтам, а вот в WIN_AVR такой флаг есть и указатель на метод равен указателю на данные.


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
Ivan.
Дата 22.8.2011, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



вот что получилось на данный момент:
Код

#define PROPERTY_PARENT(TObj) (reinterpret_cast<TObj*>(reinterpret_cast<int>(this) - reinterpret_cast<int>(&(reinterpret_cast<TObj*>(1)->__PROP)) + 1))
#define PROPERTY_INDEX(TObj)                    inline T&    operator [](int Index){ T t = {PROPERTY_PARENT(TObj), Index}; return t;}
#define PROPERTY_GET(  TObj, TVal, Get)         inline       operator TVal()       { TObj* Sender = PROPERTY_PARENT(TObj); return Get(Sender);             }
#define PROPERTY_IGET( TObj, TVal, Get)         inline       operator TVal()       {                                       return Get(Sender, Index);      }
#define PROPERTY_READ( TObj, TVal, Field)       inline       operator TVal()       { TObj* Sender = PROPERTY_PARENT(TObj); return     Sender->Field;       }
#define PROPERTY_SET(  TObj, TVal,       Set)   inline TObj& operator = (TVal Val) { TObj* Sender = PROPERTY_PARENT(TObj);        Set(Sender, Val);        return *Sender; }
#define PROPERTY_ISET( TObj, TVal,       Set)   inline TObj& operator = (TVal Val) {                                              Set(Sender, Val, Index); return *Sender; }
#define PROPERTY_WRITE(TObj, TVal,       Field) inline TObj& operator = (TVal Val) { TObj* Sender = PROPERTY_PARENT(TObj);            Sender->Field = Val; return *Sender; }
//---------------------------------------------------------------------------
#define PROPERTY_GS(   TObj, TVal, Get,  Set)   struct { PROPERTY_GET  (TObj, TVal, Get)  PROPERTY_SET  (TObj, TVal, Set)   }
#define PROPERTY_GW(   TObj, TVal, Get,  Write) struct { PROPERTY_GET  (TObj, TVal, Get)  PROPERTY_WRITE(TObj, TVal, Write) }
#define PROPERTY_RS(   TObj, TVal, Read, Set)   struct { PROPERTY_READ (TObj, TVal, Read) PROPERTY_SET  (TObj, TVal, Set)   }
#define PROPERTY_RW(   TObj, TVal, Read, Write) struct { PROPERTY_READ (TObj, TVal, Read) PROPERTY_WRITE(TObj, TVal, Write) }
#define PROPERTY_G(    TObj, TVal, Get)         struct { PROPERTY_GET  (TObj, TVal, Get)                                    }
#define PROPERTY_R(    TObj, TVal, Read)        struct { PROPERTY_READ (TObj, TVal, Read)                                   }
#define PROPERTY_S(    TObj, TVal,       Set)   struct {                                  PROPERTY_SET  (TObj, TVal, Set)   }
#define PROPERTY_W(    TObj, TVal,       Write) struct {                                  PROPERTY_WRITE(TObj, TVal, Write) }
#define PROPERTY_IGS(  TObj, TVal, Get,  Set)   struct { struct T {TObj* Sender; int Index; PROPERTY_IGET (TObj, TVal, Get)  PROPERTY_ISET (TObj, TVal, Set)}; PROPERTY_INDEX(TObj) }
#define PROPERTY_BEGIN union { struct {} __PROP
#define PROPERTY_END }
//---------------------------------------------------------------------------



--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
Ivan.
Дата 24.8.2011, 16:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Выяснилось, что описывать статические мутаторы не нужно. видимо когда я пытался решить эту задачу через темплейты я уперся в это ограничение и подумал, что это засада, а при реализации через дефайны в этом необходимость отпала.
ИТОГО все свелось к следующему:
Код

#ifndef PropertyH
#define PropertyH
//---------------------------------------------------------------------------
#define PROPERTY_PARENT(TObj) (reinterpret_cast<TObj*>(reinterpret_cast<int>(this) - reinterpret_cast<int>(&(reinterpret_cast<TObj*>(1)->__PROP)) + 1))
#define PROPERTY_INDEX(TObj)                    inline T     operator [](int Index){ T t = {PROPERTY_PARENT(TObj), Index}; return t;}
#define PROPERTY_GET(  TObj, TVal, Get)         inline       operator TVal()       { TObj* Sender = PROPERTY_PARENT(TObj); return Sender->Get();           }
#define PROPERTY_IGET( TObj, TVal, Get)         inline       operator TVal()       {                                       return Sender->Get(Index);      }
#define PROPERTY_READ( TObj, TVal, Field)       inline       operator TVal()       { TObj* Sender = PROPERTY_PARENT(TObj); return Sender->Field;           }
#define PROPERTY_SET(  TObj, TVal,       Set)   inline TObj& operator = (TVal Val) { TObj* Sender = PROPERTY_PARENT(TObj);        Sender->Set(Val);        return *Sender; }
#define PROPERTY_ISET( TObj, TVal,       Set)   inline TObj& operator = (TVal Val) {                                              Sender->Set(Val, Index); return *Sender; }
#define PROPERTY_WRITE(TObj, TVal,       Field) inline TObj& operator = (TVal Val) { TObj* Sender = PROPERTY_PARENT(TObj);        Sender->Field = Val;     return *Sender; }
//---------------------------------------------------------------------------
#define PROPERTY_GS(   TObj, TVal, Get,  Set)   struct { PROPERTY_GET  (TObj, TVal, Get)  PROPERTY_SET  (TObj, TVal, Set)   }
#define PROPERTY_GW(   TObj, TVal, Get,  Write) struct { PROPERTY_GET  (TObj, TVal, Get)  PROPERTY_WRITE(TObj, TVal, Write) }
#define PROPERTY_RS(   TObj, TVal, Read, Set)   struct { PROPERTY_READ (TObj, TVal, Read) PROPERTY_SET  (TObj, TVal, Set)   }
#define PROPERTY_RW(   TObj, TVal, Read, Write) struct { PROPERTY_READ (TObj, TVal, Read) PROPERTY_WRITE(TObj, TVal, Write) }
#define PROPERTY_G(    TObj, TVal, Get)         struct { PROPERTY_GET  (TObj, TVal, Get)                                    }
#define PROPERTY_R(    TObj, TVal, Read)        struct { PROPERTY_READ (TObj, TVal, Read)                                   }
#define PROPERTY_S(    TObj, TVal,       Set)   struct {                                  PROPERTY_SET  (TObj, TVal, Set)   }
#define PROPERTY_W(    TObj, TVal,       Write) struct {                                  PROPERTY_WRITE(TObj, TVal, Write) }
#define PROPERTY_IGS(  TObj, TVal, Get,  Set)   struct { struct T {TObj* Sender; int Index; PROPERTY_IGET (TObj, TVal, Get) PROPERTY_ISET (TObj, TVal, Set)}; PROPERTY_INDEX(TObj) }
//---------------------------------------------------------------------------
#define PROPERTY_BEGIN union { struct {} __PROP
#define PROPERTY_END }
//---------------------------------------------------------------------------
#endif

Примет:
Код

class Tclass1 {
    int FVal;
    int FArray[10];
    void SetVal(int Val) {FVal = Val;}
    int GetVal() {return FVal;}
    void SetArray(int Val, int Index) {if ((unsigned)Index < sizeof(FArray) / sizeof(FArray[0])) FArray[Index] = Val;}
    int GetArray(int Index) {if ((unsigned)Index < sizeof(FArray) / sizeof(FArray[0])) return FArray[Index]; return 0;}
public:
    PROPERTY_BEGIN;
        PROPERTY_RS(Tclass1, int, FVal, SetVal) Val1;
        PROPERTY_GW(Tclass1, int, GetVal, FVal) Val2;
        PROPERTY_RW(Tclass1, int, FVal, FVal) Val3;
        PROPERTY_IGS(Tclass1, int, GetArray, SetArray) Array;
    PROPERTY_END;
} t;
//---------------------------------------------------------------------------
int main(){
    t.Val1 = 1;
    t.Val2 = t.Val1;
    t.Array[10] = t.Val3;
    PORTB = t.Array[10];
}
//---------------------------------------------------------------------------

При рассмотрении ассемблера:
В поле t.FVal помещено значение 1;
Действие t.Val2 = t.Val1; было проигнорировано, так как это копирование самого себя, а переменная не является volatile;
Действие t.Array[10] = t.Val3; было проигнорировано, так как Index лежит за пределами массива FArray;
В PORTB выдан 0, так как по условию, если Index лежит за пределами массива - getter возвращает 0.

Остались следующие неудобства:
- необходимость описывать блок пропертей;
- разные дефайны для описания разных пропертей;
- и необходимость описывать название класса хозяина проперти.

Это сообщение отредактировал(а) Ivan. - 24.8.2011, 17:07


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
mes
Дата 24.8.2011, 18:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(Ivan. @  24.8.2011,  15:58 Найти цитируемый пост)
- и необходимость описывать название класса хозяина проперти.

а что заменить это внутренним тайпдефом разве не получается ?



--------------------
PM MAIL WWW   Вверх
Ivan.
Дата 24.8.2011, 18:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Цитата(mes @  24.8.2011,  18:19 Найти цитируемый пост)
а что заменить это внутренним тайпдефом разве не получается ?

приведи пример пожалуйста. что то в голову ничего не идет


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
mes
Дата 24.8.2011, 19:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



что то типа :
Код

#define PROPERTY_BEGIN(T) union { typedef T Hander; struct {} __PROP
#define PROPERTY_PARENT (reinterpret_cast<Handler*>(reinterpret_cast<int>(this) -...
#define PROPERTY_SET(TVal,       Set)   inline Handler& operator = (TVal Val) { Handler* Sender = PROPERTY_PARENT;        Sender->Set(Val);        return *Sender; }


Это сообщение отредактировал(а) mes - 24.8.2011, 19:37


--------------------
PM MAIL WWW   Вверх
Ivan.
Дата 25.8.2011, 10:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



ну то есть вынести в объявление блока пропертей - логично


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
Ivan.
Дата 25.8.2011, 11:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



обновленный вариант:
Код

#ifndef PropertyH
#define PropertyH
//---------------------------------------------------------------------------
#define PROPERTY_PARENT (reinterpret_cast<TObj*>(reinterpret_cast<int>(this) - reinterpret_cast<int>(&(reinterpret_cast<TObj*>(1)->__PROP)) + 1))
#define PROPERTY_INDEX                    inline T     operator [](int Index){ T t = {PROPERTY_PARENT, Index}; return t;}
#define PROPERTY_GET(  TVal, Get)         inline       operator TVal()       { TObj* Sender = PROPERTY_PARENT; return Sender->Get();           }
#define PROPERTY_IGET( TVal, Get)         inline       operator TVal()       {                                 return Sender->Get(Index);      }
#define PROPERTY_READ( TVal, Field)       inline       operator TVal()       { TObj* Sender = PROPERTY_PARENT; return Sender->Field;           }
#define PROPERTY_SET(  TVal,       Set)   inline TObj& operator = (TVal Val) { TObj* Sender = PROPERTY_PARENT;        Sender->Set(Val);        return *Sender; }
#define PROPERTY_ISET( TVal,       Set)   inline TObj& operator = (TVal Val) {                                        Sender->Set(Val, Index); return *Sender; }
#define PROPERTY_WRITE(TVal,       Field) inline TObj& operator = (TVal Val) { TObj* Sender = PROPERTY_PARENT;        Sender->Field = Val;     return *Sender; }
//---------------------------------------------------------------------------
#define PROPERTY_GS(   TVal, Get,  Set)   struct { PROPERTY_GET (TVal, Get)  PROPERTY_SET  (TVal, Set)   }
#define PROPERTY_GW(   TVal, Get,  Write) struct { PROPERTY_GET (TVal, Get)  PROPERTY_WRITE(TVal, Write) }
#define PROPERTY_RS(   TVal, Read, Set)   struct { PROPERTY_READ(TVal, Read) PROPERTY_SET  (TVal, Set)   }
#define PROPERTY_RW(   TVal, Read, Write) struct { PROPERTY_READ(TVal, Read) PROPERTY_WRITE(TVal, Write) }
#define PROPERTY_G(    TVal, Get)         struct { PROPERTY_GET (TVal, Get)                              }
#define PROPERTY_R(    TVal, Read)        struct { PROPERTY_READ(TVal, Read)                             }
#define PROPERTY_S(    TVal,       Set)   struct {                           PROPERTY_SET  (TVal, Set)   }
#define PROPERTY_W(    TVal,       Write) struct {                           PROPERTY_WRITE(TVal, Write) }
#define PROPERTY_IGS(  TVal, Get,  Set)   struct { struct T {TObj* Sender; int Index; PROPERTY_IGET (TVal, Get) PROPERTY_ISET (TVal, Set)}; PROPERTY_INDEX }
//---------------------------------------------------------------------------
#define PROPERTY_BEGIN(TParent) typedef TParent TObj; union { struct {} __PROP
#define PROPERTY_END }
//---------------------------------------------------------------------------
#endif

пример:
Код

class Tclass1 {
    int FVal;
    int FArray[10];
    void SetVal(int Val) {FVal = Val;}
    int GetVal() {return FVal;}
    void SetArray(int Val, int Index) {if ((unsigned)Index < sizeof(FArray) / sizeof(FArray[0])) FArray[Index] = Val;}
    int GetArray(int Index) {if ((unsigned)Index < sizeof(FArray) / sizeof(FArray[0])) return FArray[Index]; return 0;}
public:
    PROPERTY_BEGIN(Tclass1);
        PROPERTY_RS(int, FVal, SetVal) Val1;
        PROPERTY_GW(int, GetVal, FVal) Val2;
        PROPERTY_RW(int, FVal, FVal) Val3;
        PROPERTY_IGS(int, GetArray, SetArray) Array;
    PROPERTY_END;
} t;
//---------------------------------------------------------------------------
int main(){
    t.Val1 = 1;
    t.Val2 = t.Val1;
    t.Array[10] = t.Val3;
    PORTB = t.Array[10];
}



--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
boostcoder
Дата 10.9.2011, 12:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



Ivan., я так понял, что при использовании проперти совместно с массивами, без гетера и сетера не обойтись?

Добавлено через 5 минут и 15 секунд
думаю, что все же нужна возможность использовать проперти совместно с массивами но без гетера и сетера.
PM WWW   Вверх
boostcoder
Дата 10.9.2011, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


pattern`щик
****


Профиль
Группа: Завсегдатай
Сообщений: 5458
Регистрация: 1.4.2010

Репутация: 49
Всего: 110



при использовании type_traits и SFINAE, вместо макросов: PROPERTY_GS, PROPERTY_GW, PROPERTY_RS, PROPERTY_RW, PROPERTY_G, PROPERTY_R, PROPERTY_S, PROPERTY_W, PROPERTY_IGS, осталось бы всего два: PROPERTY_GET и PROPERTY_SET. которые были бы применимы как к членам-данным включая массивы, так и к сетерам/гетерам.

Это сообщение отредактировал(а) boostcoder - 10.9.2011, 12:35
PM WWW   Вверх
Ivan.
Дата 15.9.2011, 20:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



я долго пытался решить эту задачу с помощью template, я бы даже сказал, не один год.
вот так вот спишь ночью и вдруг приходит сонная мысль - "вот же оно решение!, в теории все должно работать". просыпаешься, начинаешь реализовывать и опять та же самая непреодолимая стена.
дело в том, что определение смещения поля от корня класса:
Код
(reinterpret_cast<TObj*>(reinterpret_cast<int>(this) - reinterpret_cast<int>(&(reinterpret_cast<TObj*>(1)->__PROP)) + 1))
не является константой и его нельзя применить как параметр template. в define оно хорошо применяется, ну и что, что не константа, компилятор все ровно ее с оптимизирует на этапе компиляции.


--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
Ivan.
Дата 16.9.2011, 08:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 2.11.2004

Репутация: 1
Всего: 2



Цитата(boostcoder @  10.9.2011,  12:00 Найти цитируемый пост)
Ivan., я так понял, что при использовании проперти совместно с массивами, без гетера и сетера не обойтись? думаю, что все же нужна возможность использовать проперти совместно с массивами но без гетера и сетера.

да вроде бы есть уже:
Код
PROPERTY_R(int*, FArray) Array;
вот тебе и указатель на массив, а дальше бери от него [].
вот с сочетанием [геттера или сеттера] и прямого обращения - тут немного сложнее.

Добавлено через 6 минут и 47 секунд
даже я бы сказал, что лучше вот так:
Код
PROPERTY_R(int* const, FArray) Array;



--------------------
Я могу ВСЁ, вопрос - сколько времени у меня это займет!
PM MAIL ICQ   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0740 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.