Re[3]: Пропертя
От: Erop Россия  
Дата: 12.05.12 18:36
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>- для скрытия реализации

_>
_>class A {
_>  List list; // потом могу переделать по другому и в других местах ничего не меняем.
_>  public void Add(object a) { list.Add(); }
_>  property int Count { get { return list.Count; } }
_>}
_>


Дык это,
_>class A {
  List list; // потом могу переделать по другому и в других местах ничего не меняем.
public:
  void Add(object a) { list.Add(); }
  int Count() const { return list.Count; }
};


_>- Что бы не писать функции getX setX

_>
_>struct SomeInterface {
_>  virtual int getX()=0;
_>  virtual int setX(int x)=0
_>};
_>

Это я не понял, к чему и зачем.

_>было

_>
_>class A {
_>  public int X;
_>};
_>


Что за проблема?
Пишешь шаблон, типа
template<typename T> class debug_wrapper {
private:
    T data;
protected:
    T& Data() { return data; }
    const T& Data() const { return data; }
public:
    // тут кучка конструкторов, с вынесенным определением тела
    // тут кучка операторов, с вынесенным определением тела

    operator const T&() const { return Data(); }
    operator T&() { return Data(); }
};


Вклюяаешь это в свои любимые отладочные тузы. И потом пишешь что-то типа:
class A {
public:
    struct xxx_prop : debug_wrapper<int> {
        void operator = ( int newValue )
        {
            this->Data() = newValue;
        }
    } X;
};


А если немного больше поработать, то можно сделать так, что можно будет написать таким образом:
class A {
public:
    struct xxx_prop : debug_wrapper<int, xxx_prop> {
        void OnNewValue() {
            if( this->Data() == 100 ) {
                this->Data() = 200;
            }
        }
    } X;
};


_>стало

_>
_>class A {
_>  int x;
_>  public int X { get { return x; }
_>    set {
_>      if (value==100) 
_>         Debug.BreakPoint();
_>      x=value;
_>    }
_> }
_>}
_>

А тут вообще не факт, что какой-то клиентский код не нагнётся.

_>- Можно использовать для валидации и оповещении об измении поля.

_>
_>class A {
_>  int x;
_>  Validator validator;
_>  Notifier notifier;
_>  public int X { get { return x; }
_>    set {
_>      validator.validate(x);
_>      if (x!=value) {
_>        x=value;
_>        notifier.notify_subscribers();
_>      }
_>    }
_> }
_>}
_>


Мульку с шаблоном можно точно так же.

_>при этом из вне синтаксис как к обычному полю a.X=a.X+1;

Только это вот и плохо.
Совсем нет никакого желания, добавить в язчк такую граблю, что a.X++ может без объявления войны превратиться в какое-то чудовище...
_>и внутренние изменения переход от поля к гетерам и сетерам не приводит к изменению остального кода.

Это неправда.
Вот представь себе, например, что надо куда-то отдать int* для заполнения
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Пропертя
От: Kingofastellarwar Украина  
Дата: 12.05.12 18:39
Оценка: -2
Здравствуйте, Erop, Вы писали:

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


K>>как просто у вас, а если вам интерфес нужен а не класс?


E>
E>class IService
E>{
E>public:
E>   virtual IMemeber* GetMember() = 0;
E>};

E>class CService : public IService
E>{
E>   CMember MemberImpl;
E>   virtual IMemeber* GetMember() { return &MemberImpl; }
E>};

E>Коротко, ясно и для интеропа с другими языками лучше приспособленно...

вот так обычно в с++ так и заканчиваются решения простых задач: изврат и разведение рук
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[5]: Пропертя
От: Erop Россия  
Дата: 12.05.12 18:41
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>>>как просто у вас, а если вам интерфес нужен а не класс?


E>>[ccode]

E>>class IService
E>>{
E>>public:
E>> virtual IMemeber* GetMember() = 0;
E>>};

K>вот так обычно в с++ так и заканчиваются решения простых задач: изврат и разведение рук

В чём изврат?
В С++ это стандартный способ интерфейса к аггрегированному объекту...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[21]: Пропертя
От: Vamp Россия  
Дата: 12.05.12 18:41
Оценка:
E>Например, почему бы не иметь возможности работать с типами в СТ, как-то их декоспозицию осуществлять, менять и т. д.
E>Какие-то такие возможности даёт шаблонная магия, но очень бледные.
Я с этим я, кстати, не спорю. Например, я в упор не понимаю, почему превратить тип в const и получить ссылку на него можно с помощью встроенных средств языка, а наоборот — только путем шаблонов и их специализации. А это плохо по целому ряду причин, включая отсутствие нормальной диагностики ошибок.
Пример — я хочу объявить шаблонную функцию, принимающую аргумент исключительно по неконстантной ссылке — потому что внутри я буду его менять.
Попытка:

template <class T>
void n1(T& t) {
    ++t;
}


И не дай бог кто-то вызовет эту функцию с константным аргументом, например:

const int i = 10;
n1(i)


Ошибка отрепортится в недрах n1, со всем счастием репортов из шаблонов.
А мне нужно, чтобы я мог написать что-то вроде n1(non_const T& ) — и компилятор четко сказал, что тип требуется неконстантный. Я многого хочу?


E>Потом рефлексия. Почему бе не дать, хотя бы в СТ возможность проитерировать все методы класса, например?

Теоретически да. Практическая польза невелика в связи со всяким увлекательным наследованием.
Да здравствует мыло душистое и веревка пушистая.
Re[22]: Пропертя
От: Erop Россия  
Дата: 12.05.12 18:47
Оценка:
Здравствуйте, Vamp, Вы писали:

E>>Потом рефлексия. Почему бе не дать, хотя бы в СТ возможность проитерировать все методы класса, например?

V>Теоретически да. Практическая польза невелика в связи со всяким увлекательным наследованием.

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

Скажем, такой хитрый шаблон, который всегда применяеся к MDT, как-то перебирает его интерфейс и модифицирует его.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: Пропертя
От: Ops Россия  
Дата: 12.05.12 19:08
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Ошибка отрепортится в недрах n1, со всем счастием репортов из шаблонов.

V>А мне нужно, чтобы я мог написать что-то вроде n1(non_const T& ) — и компилятор четко сказал, что тип требуется неконстантный. Я многого хочу?

Ну в C++11 вроде выдали костыли для этого (type traits), в бусте и так давно были.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[23]: Пропертя
От: Erop Россия  
Дата: 12.05.12 19:20
Оценка:
Здравствуйте, Ops, Вы писали:

Ops>Ну в C++11 вроде выдали костыли для этого (type traits), в бусте и так давно были.


Криво всё это и сложно.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[22]: Пропертя
От: Erop Россия  
Дата: 12.05.12 19:24
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Я с этим я, кстати, не спорю. Например, я в упор не понимаю, почему превратить тип в const и получить ссылку на него можно с помощью встроенных средств языка, а наоборот — только путем шаблонов и их специализации. А это плохо по целому ряду причин, включая отсутствие нормальной диагностики ошибок.

V>Пример — я хочу объявить шаблонную функцию, принимающую аргумент исключительно по неконстантной ссылке — потому что внутри я буду его менять.
Всё не совсем так уж плохо.
template<class T>
void f( const T& t ) { t.Arg_of_f_must_be_mutable(); }
template <class T>
void n1(T& t) {
    ++t;
}

V>И не дай бог кто-то вызовет эту функцию с константным аргументом, например:
и всё будет хорошо, но всё равно геморрно так писать.

V>
V>const int i = 10;
V>n1(i)

V>
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[24]: Пропертя
От: Ops Россия  
Дата: 12.05.12 19:46
Оценка:
Здравствуйте, Erop, Вы писали:

E>Криво всё это и сложно.


Так я ж и написал про костыли. Зато работает http://ideone.com/xhVFS
Да и не так уж сложно...
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[4]: Пропертя
От: kov_serg Россия  
Дата: 12.05.12 21:53
Оценка:
Здравствуйте, Erop, Вы писали:

_>>- Что бы не писать функции getX setX

_>>
_>>struct SomeInterface {
_>>  virtual int getX()=0;
_>>  virtual int setX(int x)=0
_>>};
_>>

E>Это я не понял, к чему и зачем.
что бы запись была более короткой
int X { get; set; }


E>Что за проблема?

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

E>Пишешь шаблон, типа
template<typename T> class debug_wrapper {
E>private:
E>    T data;
E>protected:
E>    T& Data() { return data; }
E>    const T& Data() const { return data; }
E>public:
E>    // тут кучка конструкторов, с вынесенным определением тела
E>    // тут кучка операторов, с вынесенным определением тела
E>    operator const T&() const { return Data(); }
E>    operator T&() { return Data(); }
E>};


главная проблема очень простая — я не могу достать класс родитель из этого wrapper-а
struct Parent {
  struct _X {
     int v;
     Parent* parent;
     _X() { v=11; }
     operator int () { return v; }
     _X& operator = (int rv) { controller->assign("X",v,rv); return *this; }
  } X;
  SomeController controller;
  Parent() { 
    X.parent=this;
  }
};

а для каждого поля делать указатель накладно, и неудобно инициализировать.
я пользуюсь костылями вида
struct Obj {
...
ModelField<int> X() DECL_FIELD(int,x,123);
...
};
void usage(Obj *p) {
  int x=p->X();
  p->X()=432;
}

мне универсальность не нужна. просто под конкретную задачу написано.

...
_>>стало
_>>
_>>class A {
_>>  int x;
_>>  public int X { get { return x; }
_>>    set {
_>>      if (value==100) 
_>>         Debug.BreakPoint();
_>>      x=value;
_>>    }
_>> }
_>>}
_>>

E>А тут вообще не факт, что какой-то клиентский код не нагнётся.
не нагнётся.

_>>- Можно использовать для валидации и оповещении об измении поля.

_>>
_>>class A {
_>>  int x;
_>>  Validator validator;
_>>  Notifier notifier;
_>>  public int X { get { return x; }
_>>    set {
_>>      validator.validate(x);
_>>      if (x!=value) {
_>>        x=value;
_>>        notifier.notify_subscribers();
_>>      }
_>>    }
_>> }
_>>}
_>>

E>Мульку с шаблоном можно точно так же.
и как?

_>>при этом из вне синтаксис как к обычному полю a.X=a.X+1;

E>Только это вот и плохо.
E>Совсем нет никакого желания, добавить в язык такую граблю, что a.X++ может без объявления войны превратиться в какое-то чудовище...
любой инструмент можно использовать не по назначению.
поэтому мне больше всего нравится связка C + lua. низкоуровневый язык без заморочек + просто динамический легко расширяемый язык, который позволяет описывать всякую ерунду (которой обычно много во всяких ui), коротко и ясно. при этом эта ерунда не требует высокого быстродействия.
Оба языка просто портируются, имеют низкий порог вхождения.

_>>и внутренние изменения переход от поля к гетерам и сетерам не приводит к изменению остального кода.

E>Это неправда.
E>Вот представь себе, например, что надо куда-то отдать int* для заполнения
легко представляю. но это всего лишь особенность языка. да и потом там где используются пропертя указатели на них нафиг не нужны.
замена int на хитрую структуру тоже на поведётся на int*.
Re[5]: Пропертя
От: Erop Россия  
Дата: 12.05.12 22:27
Оценка: +1
Здравствуйте, kov_serg, Вы писали:

_>что бы запись была более короткой

_>
_>int X { get; set; }
_>


Запись
struct XXX {
    int X;
};
ещё короче...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Пропертя
От: Erop Россия  
Дата: 12.05.12 22:35
Оценка: +2 -1
Здравствуйте, kov_serg, Вы писали:

E>>Что за проблема?

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

IMHO, пропертя -- это не просто, а наоборот, оч. сложно.


_>главная проблема очень простая — я не могу достать класс родитель из этого wrapper-а


_>а для каждого поля делать указатель накладно, и неудобно инициализировать.

А зачем он нужен?
Ты привёл несколько примеров использования пропертей, там нигде аггрегирующийй обект нужен не был...


_>мне универсальность не нужна. просто под конкретную задачу написано.

IMHO, просто не надо пропети под С++ использовать. Идея сама по себе против шерсти.

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

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

E>>А тут вообще не факт, что какой-то клиентский код не нагнётся.

_>не нагнётся.

Откуда следует, что не нагнётся?

E>>Мульку с шаблоном можно точно так же.

_>и как?


Подписываешь в конструкторе объекта агрегатора на уведомлени от полей того, кого надо...

E>>Вот представь себе, например, что надо куда-то отдать int* для заполнения

_>легко представляю. но это всего лишь особенность языка. да и потом там где используются пропертя указатели на них нафиг не нужны.
_>замена int на хитрую структуру тоже на поведётся на int*.

Да. Я вообще считаю подход с пропертями тухлым. Архитектурной ошибкой.
Правила поведения системы, вместо того, что бы быть где-то декларативно выписанными, размазываются по каким-то левым сеттерам и геттерам.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Пропертя
От: johny5 Новая Зеландия
Дата: 13.05.12 14:48
Оценка: +1
Здравствуйте, Kingofastellarwar, Вы писали:

E>>class CService : public IService

E>>{
E>> CMember MemberImpl;
E>> virtual IMemeber* GetMember() { return &MemberImpl; }
E>>};[/ccode]
E>>Коротко, ясно и для интеропа с другими языками лучше приспособленно...

K>вот так обычно в с++ так и заканчиваются решения простых задач: изврат и разведение рук


Чувак, другой язык это не другой синтаксический сахарок но и другая парадигма.
Re[6]: Пропертя
От: Kingofastellarwar Украина  
Дата: 13.05.12 14:57
Оценка:
Здравствуйте, johny5, Вы писали:

J>Чувак, другой язык это не другой синтаксический сахарок но и другая парадигма.


с такими фразами лучше в политику, "парадигмой" я могу оправдать всё что угодно и где угодно
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[6]: Пропертя
От: johny5 Новая Зеландия
Дата: 13.05.12 15:05
Оценка:
Здравствуйте, Erop, Вы писали:

E>Хотя я согласен, что в С++ можно было бы добавить механизм, который бы позволял из поля найти this объемлющего объекта, но тогда полю пришлось бы иметь уникальный тип. Ну да и фиг бы с ним.


Именно так я накидал PROPERTY макро:

#define PROPERTY(PropertyName, OwnerType_, Type, InternalType, GetterName, SetterName)  \
    template<typename OwnerType>
    struct Property##PropertyName : public PropertyValueHolder__<InternalType>
....
... //указатель на родительский класс получается вот так
    const OwnerType* get_owner_this() const
    {
        return (const OwnerType*)(((const char*)this) - OFFSETOF(OwnerType, OwnerType::PropertyName));
    }

.. // класс с уникальным именем
    Property##PropertyName <OwnerType_> PropertyName;


и с помощью трюка что шаблонные функции инстанциируются только в месте использования, вполне легально было заюзать OFFSETOF на ещё не доопределённый класс.

Замечательно работало, правда использовал лишь единожды да и помоему позднее таки выкинул.
Если нужно, могу впостить код целиком.
Re[7]: Пропертя
От: Ops Россия  
Дата: 13.05.12 15:16
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>с такими фразами лучше в политику, "парадигмой" я могу оправдать всё что угодно и где угодно


Не знаю, насчет политики, но с твоим кодом явно не в C++.
Переубедить Вас, к сожалению, мне не удастся, поэтому сразу перейду к оскорблениям.
Re[7]: Пропертя
От: johny5 Новая Зеландия
Дата: 13.05.12 15:38
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:

K>с такими фразами лучше в политику, "парадигмой" я могу оправдать всё что угодно и где угодно


Ты опять не понимаешь, языки это не синтаксические сахарки к одному и тому же. Вот ты хочешь от С++ то-же, что сделано в С# но только чтобы "быстрее". Разве ты сам не видишь тут противоречия?

С++ проектировался (парадигма была такая), чтобы быть быстрее.
С# проектировался, чтобы мм.. быть доступнее начинающим.

Вот вы даже в оригинальном посте поленились указатели расставить, видно что внимания к этому вопросу (принципам программирования на С++) совсем нет, нуно просто склепать. Я вам предложу вариант, именно то что вы хотели — без виртуального вызова:

class IService
{
public:
   IMemeber* const Member;

protected:
   IService(IMember* m) : Member(m) {}
};

class CService : public IService
{
    CMemberImpl  member;
public:
    CService() : IService(&member)
    {}
}


но это лютый изврат. Вариант Егора лучше — он понятнее (в парадигме), так обычно спрашивают доп. интерфейс у объекта.

Можно ещё поплясать на множественном наследовании, отнаследовать несколько интерфейсов и спрашивать их через dynamic_cast<>
class IService
{
    virtual something_else...
};

class CService : public IService, CMemberImpl
{
}


либо написать свою реализацию virtual QueryInterface(enum.. );, либо инкапсулировать интерфейсы друг в друга.

Вообще имхо подобная проблема возникает редко, нужно бы посмотреть под капот, откуда он такой возникает и избавиться от него. У меня есть некие преположения почему подобные извраты вдруг потребовались...
Re[8]: Пропертя
От: Kingofastellarwar Украина  
Дата: 13.05.12 15:51
Оценка:
Здравствуйте, johny5, Вы писали:

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


K>>с такими фразами лучше в политику, "парадигмой" я могу оправдать всё что угодно и где угодно


J>Ты опять не понимаешь, языки это не синтаксические сахарки к одному и тому же. Вот ты хочешь от С++ то-же, что сделано в С# но только чтобы "быстрее". Разве ты сам не видишь тут противоречия?


J>С++ проектировался (парадигма была такая), чтобы быть быстрее.

J>С# проектировался, чтобы мм.. быть доступнее начинающим.

J>Вот вы даже в оригинальном посте поленились указатели расставить, видно что внимания к этому вопросу (принципам программирования на С++) совсем нет, нуно просто склепать. Я вам предложу вариант, именно то что вы хотели — без виртуального вызова:


J>
J>class IService
J>{
J>public:
J>   IMemeber* const Member;

J>protected:
J>   IService(IMember* m) : Member(m) {}
J>};

J>class CService : public IService
J>{
J>    CMemberImpl  member;
J>public:
J>    CService() : IService(&member)
J>    {}
J>}
J>


J>но это лютый изврат. Вариант Егора лучше — он понятнее (в парадигме), так обычно спрашивают доп. интерфейс у объекта.


он не прокатит в куче случаев, например если у нас

CMemberImpl * member;
а не
CMemberImpl member;

придется писать
IMemeber** const Member;
а это порно
Я изъездил эту страну вдоль и поперек, общался с умнейшими людьми и я могу вам ручаться в том, что обработка данных является лишь причудой, мода на которую продержится не более года. (с) Эксперт, авторитет и профессионал из 1957 г.
Re[9]: Пропертя
От: johny5 Новая Зеландия
Дата: 13.05.12 16:13
Оценка:
Здравствуйте, Kingofastellarwar, Вы писали:


K>он не прокатит в куче случаев, например если у нас


K>CMemberImpl * member;

K>а не
K>CMemberImpl member;

K>придется писать

K> IMemeber** const Member;
K>а это порно

Ну если у вас меняется имплементация IMember в рантайме, тогда вариант Егора тут выглядит чище, хоть он и тяжелее из-за виртуального вызова. Можно и было бы просто сбросить константность указателя Member в IService и менять его вместе со сменой имплементации IMember*, избегая двойного указателя.

Только уже опасно, т.к. клиент подобного интерфейса может скэшировать старый указатель. Я бы тогда лучше инкапсулировал IMember интерфейс в IService, чтобы огородить клиента от подобных проблем.
Re[7]: Пропертя
От: Erop Россия  
Дата: 13.05.12 20:56
Оценка:
Здравствуйте, johny5, Вы писали:

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

J>Если нужно, могу впостить код целиком.

UB на UB + виртуальная база всё нагнёт...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.