Property на C++ без расширений языка
От: Undead  
Дата: 15.10.04 19:40
Оценка: :)
Вот попробовал написать код поддержки так называемых свойств (как в C#).
Есть замечания и предложения по дизайну или ссылки на уже существующие реализации?

использование:
class Temp
{
public:
    Temp(): Length(this, getLength, setLength), len(0) {}
    Property<Temp, float, PropertyType::GetSet> Length;
private:
    float getLength() const { std::cout << "get called\n"; return len; }
    void setLength(float newLength) { std::cout << "set called\n"; len = newLength;}    
    float len;
};

int main()
{
    Temp t;
    t.Length = t.Length+2;
    std::cout << t.Length;
}


реализация:
#pragma once

namespace PropertyType { enum Type{ Get, Set, GetSet }; };
template <class Class, typename T, PropertyType::Type> class Property;

template <class Class, typename T>
class Property<Class, T, PropertyType::Get>
{
protected:
    typedef typename T (Class::*GetFunc)(void) const;
public:
    Property(Class* ptr, GetFunc g): obj_ptr(ptr), get(g) {}
    operator typename T() const { return (obj_ptr->*get)(); }
private:
    Class* obj_ptr;
    GetFunc get;
};

template <class Class, typename T>
class Property<Class, T, PropertyType::Set>
{
protected:
    typedef void (Class::*SetFunc)(typename T);
public:
    Property(Class* ptr, SetFunc s): obj_ptr(ptr), set(s) {}
    Property& operator=(const T& value)
    {
        (obj_ptr->*set)(value);
        return *this;
    }
private:
    Class* obj_ptr;
    SetFunc set;
};

template <class Class, typename T> 
class Property<Class, T, PropertyType::GetSet>:
    public Property<Class, T, PropertyType::Get>, public Property<Class, T, PropertyType::Set>
{
    typedef Property<Class, T, PropertyType::Get> BaseGet;
    typedef Property<Class, T, PropertyType::Set> BaseSet;
public:
    Property(Class* ptr, GetFunc g, SetFunc s): BaseGet(ptr, g), BaseSet(ptr, s) {}
    Property& operator=(const T& value)
    {
        BaseSet::operator=(value);
        return *this;
    }
};


Мои собственные замечания:
использование:
1) при использовании парит писать имя класса, которому свойство принадлежит
2) использование this в списке инициализации конструктора не безопасно.
реализация:
1) при множественном наследовании объект GetSet занимает 16 байт вместо положенных 12.
2) operator= не наследуется, поэтому приходится писать дублирующий код в GetSet
Re: Property на C++ без расширений языка
От: vdimas Россия  
Дата: 16.10.04 01:12
Оценка: +1
Здравствуйте, Undead, Вы писали:

U>Вот попробовал написать код поддержки так называемых свойств (как в C#).

U>Есть замечания и предложения по дизайну или ссылки на уже существующие реализации?

— можно сеттеры и геттеры вынести в параметры шаблона
— вместо хранения this объекта в шаблоне использовать смещение от this этого проперти

т.е. само пропертине должно хранить данных, в параметрах шаблона можно все указать,
получишь 1 байт на проперти в целевом классе

-------------------
__declspec(property ...)

а вообще, заканчивайте вы с этими пропертями на С++
Re: Property на C++ без расширений языка
От: Nuald Россия http://nuald.blogspot.com
Дата: 16.10.04 01:29
Оценка: 1 (1)
Здравствуйте, Undead, Вы писали:

U>Вот попробовал написать код поддержки так называемых свойств (как в C#).

U>Есть замечания и предложения по дизайну или ссылки на уже существующие реализации?

Статья: "Свойства в С++"
Автор(ы): Денис Майдыковский

В этой статье автор рассматривает различные способы реализации свойств в
стиле Visual Basic на C++. Некоторые способы специфичны для Visual C++,
тогда как другие годятся для применения в любой программе, написанной на
языке C++.
Re[2]: Property на C++ без расширений языка
От: Undead  
Дата: 16.10.04 07:22
Оценка:
Веселая ссылка, прямо один в один
Re[2]: Property на C++ без расширений языка
От: Shady Россия  
Дата: 16.10.04 07:40
Оценка:
Здравствуйте, vdimas, Вы писали:

V>а вообще, заканчивайте вы с этими пропертями на С++

а это типа намёк на c#?
... << RSDN@Home 1.1.3 stable >>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[2]: Property на C++ без расширений языка
От: Undead  
Дата: 16.10.04 07:43
Оценка:
Вы писали:
V>- можно сеттеры и геттеры вынести в параметры шаблона
Отлично, вынес в параметр шаблона, так намного экономней и красивей.

V>- вместо хранения this объекта в шаблоне использовать смещение от this этого проперти

А вот этого не понял. Можно подробней?
Re[3]: Property на C++ без расширений языка
От: vdimas Россия  
Дата: 16.10.04 09:39
Оценка: 1 (1)
Здравствуйте, Undead, Вы писали:

U>Вы писали:

V>>- можно сеттеры и геттеры вынести в параметры шаблона
U>Отлично, вынес в параметр шаблона, так намного экономней и красивей.

V>>- вместо хранения this объекта в шаблоне использовать смещение от this этого проперти

U>А вот этого не понял. Можно подробней?

да, можно,
есть такая штука в С++ — offsetof, причем, раз это константа, то ты ее можешь тоже как параметр шаблона указать.
а потом, из this инстанса проперти обратно по смещению можешь получить this объекта-парента, и таким образом — не нужно его хранить в экземпляре проперти.

...навороченное может получиться объявление, но тут и макросами разбавить не грех.
Re[3]: Property на C++ без расширений языка
От: vdimas Россия  
Дата: 16.10.04 09:43
Оценка:
Здравствуйте, Shady, Вы писали:

V>>а вообще, заканчивайте вы с этими пропертями на С++

S>а это типа намёк на c#?

вот еще...
просто не такое уж это востребованное качество — доступ к св-вам в стиле OPascal или там VB.

на худой конец, если ОЧЕНЬ хочется, чем не устраивает __declspec(property ...)?, тем более, что он и индексированные проперти поддерживает (а C#, кстати, нет).
Re[4]: Property на C++ без расширений языка
От: Shady Россия  
Дата: 16.10.04 09:48
Оценка:
Здравствуйте, vdimas, Вы писали:

V>вот еще...

V>просто не такое уж это востребованное качество — доступ к св-вам в стиле OPascal или там VB.
Ну почему же, очень удобная фича...

V>на худой конец, если ОЧЕНЬ хочется, чем не устраивает __declspec(property ...)?, тем более, что он и индексированные проперти поддерживает (а C#, кстати, нет).

Ну да, ms specific? Увольте...
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[4]: Property на C++ без расширений языка
От: Undead  
Дата: 16.10.04 10:23
Оценка: -1
Здравствуйте, vdimas, Вы писали:

V>есть такая штука в С++ — offsetof, причем, раз это константа, то ты ее можешь тоже как параметр шаблона указать.

V>а потом, из this инстанса проперти обратно по смещению можешь получить this объекта-парента, и таким образом — не нужно его хранить в экземпляре проперти.

Ошибка: error C2027: use of undefined type 'Temp'
да и в любом случае объявление действительно слишком некрасивое получается.

V>...навороченное может получиться объявление, но тут и макросами разбавить не грех.

Макросы сами по себе грех. Хуже этого только ms specific
Re[2]: Property на C++ без расширений языка
От: Alexey Chen Чили  
Дата: 16.10.04 10:26
Оценка:
Здравствуйте, vdimas, Вы писали:

V>т.е. само пропертине должно хранить данных, в параметрах шаблона можно все указать,

V>получишь 1 байт на проперти в целевом классе
А нулевой оверхед слабо сделать?


P.S.
В понедельник опубликую.
Re[3]: Property на C++ без расширений языка
От: Shady Россия  
Дата: 16.10.04 11:11
Оценка:
Здравствуйте, Alexey Chen, Вы писали:

AC>P.S.

AC>В понедельник опубликую.
А почему в понедельник? Это так долго...
... << RSDN@Home 1.1.4 beta 3 rev. 185>>
"Man feed machine
Machine feed man"
Peter Gabriel — OVO — The Tower That Ate People
Re[4]: Property на C++ без расширений языка
От: Alexey Chen Чили  
Дата: 16.10.04 15:16
Оценка:
Здравствуйте, Shady, Вы писали:

S>Здравствуйте, Alexey Chen, Вы писали:


AC>>P.S.

AC>>В понедельник опубликую.
S>А почему в понедельник? Это так долго...

Ну если думать не хочется, могу сейчас На самом деле, все просто тривиально.
Идея в том, что ...
( для http://www.rsdn.ru/Forum/Message.aspx?mid=854815&amp;only=1 )
  union {
    getset_property<Temp, float, getLength, setLength> Length;
    get_property<Temp, float, getLength> LengthGetter;
  };
Так будет константный оверхед.

Это, кстати, решает проблему инициализации всех пропертей (вообще это ub, но работать будет) с которой у автора ошибка.
Можно еще реализовать пропертя без хранения указателя на контейнер, тогда можно поместить в обьеденени какой либо мембер котейнера, и оверхед будет нулевой.
Re[5]: Property на C++ без расширений языка
От: Undead  
Дата: 16.10.04 16:22
Оценка:
Здравствуйте, Alexey Chen, Вы писали:

AC>Это, кстати, решает проблему инициализации всех пропертей (вообще это ub, но работать будет) с которой у автора ошибка.

Я заметил ошибку, попытался модернуть, но как-то тут с этим туго оказалось

AC>Можно еще реализовать пропертя без хранения указателя на контейнер, тогда можно поместить в обьеденени какой либо мембер котейнера, и оверхед будет нулевой.

Интрузивный подход.
Re[4]: Property на C++ без расширений языка
От: Alexey Chen Чили  
Дата: 16.10.04 16:32
Оценка:
Здравствуйте, vdimas, Вы писали:

V>>>- вместо хранения this объекта в шаблоне использовать смещение от this этого проперти

U>>А вот этого не понял. Можно подробней?

V>да, можно,

V>есть такая штука в С++ — offsetof, причем, раз это константа, то ты ее можешь тоже как параметр шаблона указать.
V>а потом, из this инстанса проперти обратно по смещению можешь получить this объекта-парента, и таким образом — не нужно его хранить в экземпляре проперти.

Странно эта штука местами работает...

V>...навороченное может получиться объявление, но тут и макросами разбавить не грех.

Ну как вариант, набрасал тут ...

#include <stdio.h>

#define DECLARE_PROPERTY_(T,type,Set,Get,name) \
struct __Property_##name; friend struct __Property_##name; \
struct __Property_##name { \
  operator type () const { return resolve_(this,1)->Get(); } \
  __Property_##name& \
  operator = (const type& a) { resolve_(this,1)->Set(a); return *this; } \
  \
  template <class fake> static T* resolve_(const void* p,fake) {\
    T* _ = 0; \
    return (T*)( (char*)p - ( (char*)(&_->a) - (char*)(_) ) );\
  } \
}
#define PROPERTY(name) __Property_##name name
#define DECLARE_PROPERTY(T,type,name) DECLARE_PROPERTY_(T,type,set_##name,get_##name,name)

struct Test {

  DECLARE_PROPERTY(Test,float,a);
  DECLARE_PROPERTY(Test,float,b);

  union {
    PROPERTY(a);
    PROPERTY(b);
  };

private:

  float a_;
  float b_;
  float get_a() const  { printf("Test::Get1\n"); return a_; }
  void set_a(float val) { printf("Test::Set1\n"); a_ = val; }
  float get_b() const  { printf("Test::Get1\n"); return b_; }
  void set_b(float val) { printf("Test::Set1\n"); b_ = val; }

};
  
int main() {
  Test* t = new Test;
  printf("%d\n",sizeof(*t));
  t->a = 2;
  printf("%f\n",float(t->a));
  return 0;
}


Оверхед константный. Если в обьеденение положить каконить мембер, будет нулевой оверхед.

Кстати, вопрос нашим Гуру, так вообще делать можно? А то некоторые компилеры как-то странно ругаются.

Не работает с: Borland C++ (кто бы сомнивался), Gcc 2.95 (компиллер еррор), Sun C++ 5.5 (момбер обьеденения не может иметь оперетор = ).
Работает с: MS C++ 6/7, MWCC 3.x, DMC 8.4x, ICL8, GCC 3.2
Re[5]: Property на C++ без расширений языка
От: yxiie Украина www.enkord.com
Дата: 16.10.04 17:28
Оценка: 1 (1) +1
Здравствуйте, Alexey Chen, Вы писали:

...
AC> DECLARE_PROPERTY(Test,float,a);
AC> DECLARE_PROPERTY(Test,float,b);
...

тип в таких конструкциях всегда лучше в конце писать:

DECLARE_PROPERTY(Test,a,float);


а то типом может оказаться что-то типа pair<string, long> и будут проблемы
... << RSDN@Home 1.1.3 stable >>
Re[6]: Property на C++ без расширений языка
От: Alexey Chen Чили  
Дата: 16.10.04 18:08
Оценка:
Здравствуйте, yxiie, Вы писали:

Y>DECLARE_PROPERTY(Test,a,float);

Y>а то типом может оказаться что-то типа pair<string, long> и будут проблемы

Хм, об этом я не подумал. А макрос на этом вообще не сломается? Скажет еще, что неправильное количество аргументов.
Re[6]: Property на C++ без расширений языка
От: _nn_ www.nemerleweb.com
Дата: 16.10.04 19:41
Оценка:
Здравствуйте, yxiie, Вы писали:

Y>Здравствуйте, Alexey Chen, Вы писали:


Y>...

AC>> DECLARE_PROPERTY(Test,float,a);
AC>> DECLARE_PROPERTY(Test,float,b);
Y>...

Y>тип в таких конструкциях всегда лучше в конце писать:


Y>
Y>DECLARE_PROPERTY(Test,a,float);
Y>


Y>а то типом может оказаться что-то типа pair<string, long> и будут проблемы


Почитайте здесь
Автор: SergH
Дата: 08.10.04
и проблем не будет
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: Property на C++ без расширений языка
От: yxiie Украина www.enkord.com
Дата: 16.10.04 20:02
Оценка:
Здравствуйте, Alexey Chen, Вы писали:

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


AC>
Y>>DECLARE_PROPERTY(Test,a,float);
AC>

Y>>а то типом может оказаться что-то типа pair<string, long> и будут проблемы

AC>Хм, об этом я не подумал. А макрос на этом вообще не сломается? Скажет еще, что неправильное количество аргументов.


ну если в таком виде как сейчас, то конечно сломается, но ведь можно заюзать workaround типа моего
Автор: yxiie
Дата: 08.10.04
... << RSDN@Home 1.1.3 stable >>
Re[7]: Property на C++ без расширений языка
От: yxiie Украина www.enkord.com
Дата: 16.10.04 20:02
Оценка:
Здравствуйте, _nn_, Вы писали:

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


Y>>Здравствуйте, Alexey Chen, Вы писали:


Y>>...

AC>>> DECLARE_PROPERTY(Test,float,a);
AC>>> DECLARE_PROPERTY(Test,float,b);
Y>>...

Y>>тип в таких конструкциях всегда лучше в конце писать:


Y>>
Y>>DECLARE_PROPERTY(Test,a,float);
Y>>


Y>>а то типом может оказаться что-то типа pair<string, long> и будут проблемы


__>Почитайте здесь
Автор: SergH
Дата: 08.10.04
и проблем не будет




может вы бы сразу ссылку на мой
Автор: yxiie
Дата: 08.10.04
ответ дали бы?
... << RSDN@Home 1.1.3 stable >>
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.