Re[2]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 05.02.13 13:51
Оценка: -4
Здравствуйте, DrDred, Вы писали:

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



P>>Добрый день.


P>>Есть MSVC2010 и есть класс:


DD>[skipped]


P>>Нужен доступ к полям класса.

P>>Каждый раз писать новую функцию getX не хочется.
P>>Хотелось бы применить шаблон.
P>>Но так как имена полей разные, то шаблон применить нельзя.

P>>Вопросы:


P>>1. Как быть и что делать? Неужели нужно писать вручную все функции доступа к полям?


P>>Спасибо.


DD>Объявить поля public Или речь идет о создании только RO доступа?


Публичные поля это ересь, так учит нас Страуструп.

DD>Написать макрос?


Макросы это еще большая ересь, так учит нас Страуструп.

А если серьезно, хочется все делать по науке, с проверкой типов компилятором и все такое.
Re: доступ к полям с помощью шаблона
От: Кодт Россия  
Дата: 05.02.13 13:52
Оценка: 12 (1) -1
Здравствуйте, pepsicoca, Вы писали:

P>1. Как быть и что делать? Неужели нужно писать вручную все функции доступа к полям?


Написать на метаязыке (на макросах, короче говоря)
class A
{
  FIELD(char, 1)
  FIELD(int, 2)
  FIELD(float, 3)
};

Реализация элементарная
// склейку токенов лучше брать готовую, чем голый оператор ## и потом удивляться правилам подстановки макроаргументов
#define FIELD_NAME(suffix)  BOOST_PP_CAT(field,suffix)
#define GETTER_NAME(suffix) BOOST_PP_CAT(get,suffix)

#define FIELD(type, suffix) \
  private: \
    type FIELD_NAME(suffix); \
  public: \
    type GETTER_NAME(suffix) const { return FIELD_NAME(suffix); } \
Перекуём баги на фичи!
Re[2]: доступ к полям с помощью шаблона
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 06.02.13 09:58
Оценка: -2
Здравствуйте, Abyx, Вы писали:

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


P>>
P>>char  field1; 
P>>int   field2;
P>>float field3;
P>>


A>это называется std::tuple, или boost::fusion, в зависимости от того что вы с этими полями собираетесь делать.

А это назвается из пушки по воробьям .
Sic luceat lux!
Re[3]: доступ к полям с помощью шаблона
От: johny5 Новая Зеландия
Дата: 05.02.13 14:36
Оценка: 12 (1)
Здравствуйте, pepsicoca, Вы писали:

P>То есть на шаблонах это сделать нельзя?


Ещё можно сделать вот так:

class A
{
public:
   struct InternalData
   {
      char field1;
      int field2;
      float field3;
   };

   const InternalData&  GetData() const { return data; }

private:
   InternalData  data;
};



И да, чтоб с шаблонами:
   template<typename T>
   typename enable_if< has_key< mpl::set<AllowedAccessor1, AllowedAccessor2>, T>, const InternalData&>::type
      GetData() const { return data; }


Re[3]: доступ к полям с помощью шаблона
От: Evgeny.Panasyuk Россия  
Дата: 05.02.13 16:05
Оценка: 5 (1)
Здравствуйте, pepsicoca, Вы писали:

DD>>Объявить поля public Или речь идет о создании только RO доступа?

P>Публичные поля это ересь, так учит нас Страуструп.

Кто тебе это сказал?

http://www.artima.com/intv/goldilocks2.html

Bjarne Stroustrup: Going to the big class hierarchy is again, you write more code than you need to, and you get too much connection between different parts. I particularly dislike classes with a lot of get and set functions. That is often an indication that it shouldn't have been a class in the first place. It's just a data structure. And if it really is a data structure, make it a data structure.
My rule of thumb is that you should have a real class with an interface and a hidden representation if and only if you can consider an invariant for the class.

Bill Venners: What do you mean by invariant?

Bjarne Stroustrup: What is it that makes the object a valid object? An invariant allows you to say when the object's representation is good and when it isn't. Take a vector as a very simple example. A vector knows that it has n elements. It has a pointer to n elements. The invariant is exactly that: the pointer points to something, and that something can hold n elements. If it holds n+1 or n-1 elements, that's a bug. If that pointer is zero, it's a bug, because it doesn't point to anything. That means it's a violation of an invariant. So you have to be able to state which objects make sense. Which are good and which are bad. And you can write the interfaces so that they maintain that invariant. That's one way of keeping track that your member functions are reasonable. It's also a way of keeping track of which operations need to be member functions. Operations that don't need to mess with the representation are better done outside the class. So that you get a clean, small interface that you can understand and maintain.

Bill Venners: So the invariant justifies the existence of a class, because the class takes the responsibility for maintaining the invariant.

Bjarne Stroustrup: That's right.

Bill Venners: The invariant is a relationship between different pieces of data in the class.

Bjarne Stroustrup: Yes. If every data can have any value, then it doesn't make much sense to have a class. Take a single data structure that has a name and an address. Any string is a good name, and any string is a good address. If that's what it is, it's a structure. Just call it a struct. Don't have anything private. Don't do anything silly like having a hidden name and address field with get_name and set_address and get_name and set_name functions. Or even worse, make a virtual base class with virtual get_name and set_name functions and so on, and override it with the one and only representation. That's just elaboration. It's not necessary.

доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 05.02.13 13:34
Оценка:
Добрый день.

Есть MSVC2010 и есть класс:


class a{

char  field1; 
int   field2;
float field3;

public:

char  get1(){return field1;}
int   get2(){return field2;}
float get3(){return field3;}

//template<class T> T get(){return ???;}

};



Нужен доступ к полям класса.
Каждый раз писать новую функцию getX не хочется.
Хотелось бы применить шаблон.
Но так как имена полей разные, то шаблон применить нельзя.

Вопросы:

1. Как быть и что делать? Неужели нужно писать вручную все функции доступа к полям?

Спасибо.
Re: доступ к полям с помощью шаблона
От: DrDred Россия  
Дата: 05.02.13 13:43
Оценка:
Здравствуйте, pepsicoca, Вы писали:


P>Добрый день.


P>Есть MSVC2010 и есть класс:


[skipped]

P>Нужен доступ к полям класса.

P>Каждый раз писать новую функцию getX не хочется.
P>Хотелось бы применить шаблон.
P>Но так как имена полей разные, то шаблон применить нельзя.

P>Вопросы:


P>1. Как быть и что делать? Неужели нужно писать вручную все функции доступа к полям?


P>Спасибо.


Объявить поля public Или речь идет о создании только RO доступа?
Написать макрос?
--
WBR, Alexander
Re[2]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 05.02.13 13:58
Оценка:
Здравствуйте, Кодт, Вы писали:

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


P>>1. Как быть и что делать? Неужели нужно писать вручную все функции доступа к полям?


К>Написать на метаязыке (на макросах, короче говоря)

К>
К>class A
К>{
К>  FIELD(char, 1)
К>  FIELD(int, 2)
К>  FIELD(float, 3)
К>};
К>

К>Реализация элементарная
К>
К>// склейку токенов лучше брать готовую, чем голый оператор ## и потом удивляться правилам подстановки макроаргументов
К>#define FIELD_NAME(suffix)  BOOST_PP_CAT(field,suffix)
К>#define GETTER_NAME(suffix) BOOST_PP_CAT(get,suffix)

К>#define FIELD(type, suffix) \
К>  private: \
К>    type FIELD_NAME(suffix); \
К>  public: \
К>    type GETTER_NAME(suffix) const { return FIELD_NAME(suffix); } \

К>


То есть на шаблонах это сделать нельзя?
Re[3]: доступ к полям с помощью шаблона
От: Кодт Россия  
Дата: 05.02.13 14:28
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>То есть на шаблонах это сделать нельзя?


А как ты это себе представляешь?
Шаблоны не порождают имена, а только используют существующие. То есть, get<int> или get<1> сделать можно, а get_int или get_1 — нельзя.
Склейка токенов — это уровень лексера либо рефлекшена. Лексер — см. препроцессор. Рефлекшен — см. другой язык

Впрочем, можно написать кучу внешних функций вида
template<class T>
auto get_1(T const& t) -> decltype(t.field_1)
{ return t.field_1; }

и может быть, даже подверстать это добро в класс в виде микс-ина
template<class Final> class define_getters
{
  auto get_1() const -> decltype(((Final*)this)->field_1)
  { return ((Final*)this)->field_1; }

  auto get_2() const -> decltype(((Final*)this)->field_2)
  { return ((Final*)this)->field_2; }

  // и т.д. - нагенерить макросами
};

class A : public define_getters<A>
{
  friend class define_getters<A>;
  int field_10;
};

Но это C++11... в С++0x или 98 информацию о типе поля просто так нахаляву не извлечёшь.
Мне рисуются какие-нибудь мрачные решения со списками типов. Уж лучше сразу макросы.
Перекуём баги на фичи!
Re: доступ к полям с помощью шаблона
От: Abyx Россия  
Дата: 05.02.13 14:49
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>
P>char  field1; 
P>int   field2;
P>float field3;
P>


это называется std::tuple, или boost::fusion, в зависимости от того что вы с этими полями собираетесь делать.
In Zen We Trust
Re[2]: доступ к полям с помощью шаблона
От: Abyx Россия  
Дата: 05.02.13 14:53
Оценка:
Здравствуйте, Кодт, Вы писали:

К>
К>class A
К>{
К>  FIELD(char, 1)
К>  FIELD(int, 2)
К>  FIELD(float, 3)
К>};
К>


жуть какая.
а если их 10 и надо в начало новый добавить — все индексы руками перебивать?
In Zen We Trust
Re[3]: доступ к полям с помощью шаблона
От: Кодт Россия  
Дата: 05.02.13 20:13
Оценка:
Здравствуйте, Abyx, Вы писали:

A>жуть какая.

A>а если их 10 и надо в начало новый добавить — все индексы руками перебивать?

А это зависит от того, как раздаются имена.
Если "1", "2", "42", "foo" — то самое оно.
Если строго последовательно, то берём, скажем, BOOST_PP_SEQ_FOR_EACH_I — и рожаем последовательно
#define DECLARE_FIELDS(seq) BOOST_PP_SEQ_FOR_EACH_I(DECLARE_NTH_FIELD, fake_data, seq)
#define DECLARE_NTH_FIELD(r, data, i, elem) DECLARE_FIELD(elem, i)

class A
{
  DECLARE_FIELDS( // синтаксис непривычный, зато не требует variadic macros
    (int)
    (float)
    (char)
  )
};

Вот только много ли смысла от "надо в начало новый добавить"? Это же, скорее всего, приведёт к тотальному кровавому рефакторингу: по всему коду придётся get1 на get2 ... get9 на get10 переправлять.

Но надо заметить, что такое вот централизованное и последовательное объявление полей удобно скрещивается с шаблонным метапрограммированием — т.е. мы можем создать список типов и доступаться к полям не только по именам, созданным лексером — get1, field1, но и вычисленным — get<1>, field<1>.

И кстати сказать, тему легко развить. С помощью макросов мы каждому полю не только индекс дадим, но и произвольный тэг. И доступаться будем не только по индексу — get1, get<1>, но и по тэгу — get<foo>.
Примерно такой дизайн
class A
{
  DECLARE_FIELDS(
    ((int))
    ((float)(foo)) // именованное поле
    ((char)(bar))
    ((long))
  )
// превратится в
public:
  typedef structure<int,float,char,long> fields;
  typedef int2type<2> foo;
  typedef int2type<3> bar;
private:
  fields m_fields;
public:
  template<int I>   typename fields::get_type<I       >::type get_i() const { return m_fields.get_value<I>(); }
  template<class T> typename fields::get_type<T::value>::type get_t() const { return m_fields.get_value<T::value>(); }
};
Перекуём баги на фичи!
Re[4]: доступ к полям с помощью шаблона
От: Abyx Россия  
Дата: 05.02.13 23:00
Оценка:
Здравствуйте, Кодт, Вы писали:

К>class A

К>{
К> DECLARE_FIELDS( // синтаксис непривычный, зато не требует variadic macros
К> (int)
К> (float)
К> (char)
К> )
К>};
К>[/c]
К>Вот только много ли смысла от "надо в начало новый добавить"? Это же, скорее всего, приведёт к тотальному кровавому рефакторингу: по всему коду придётся get1 на get2 ... get9 на get10 переправлять.

если в коде есть токены "get1", "get2" и т.п. автора надо бы пристрелить.

К>Но надо заметить, что такое вот централизованное и последовательное объявление полей удобно скрещивается с шаблонным метапрограммированием — т.е. мы можем создать список типов и доступаться к полям не только по именам, созданным лексером — get1, field1, но и вычисленным — get<1>, field<1>.


круто. только для этого есть std::tuple, уже готовая, и без макросов.

----

а что кстати не так с variadic macros? они вроде во всех основных компиляторах есть
In Zen We Trust
Re[5]: доступ к полям с помощью шаблона
От: Кодт Россия  
Дата: 06.02.13 18:17
Оценка:
Здравствуйте, Abyx, Вы писали:

К>>Вот только много ли смысла от "надо в начало новый добавить"? Это же, скорее всего, приведёт к тотальному кровавому рефакторингу: по всему коду придётся get1 на get2 ... get9 на get10 переправлять.


A>если в коде есть токены "get1", "get2" и т.п. автора надо бы пристрелить.


Предлагаю заменить расстрел пожизненной правкой циферок в списках декларации.

И потом, топикстартер с этого же и начал: с токенов get1, get2... Видать, они там есть.
Но возможно, что эти токены не руками набиваются, а тоже каким-то средством автоматизации, — препроцессором или внешней тулзой.


К>>Но надо заметить, что такое вот централизованное и последовательное объявление полей удобно скрещивается с шаблонным метапрограммированием — т.е. мы можем создать список типов и доступаться к полям не только по именам, созданным лексером — get1, field1, но и вычисленным — get<1>, field<1>.


A>круто. только для этого есть std::tuple, уже готовая, и без макросов.


С помощью макросов можно сделать удобный обвес вокруг tuple.
Я не стал заостряться именно на std::tuple, написав в эскизе абстрактную structure<.....> — как всегда, здесь возможны варианты. Может, топикстартеру потребуется играться со списком типов, и припахать boost::mpl? Откуда я это знаю.


A>а что кстати не так с variadic macros? они вроде во всех основных компиляторах есть


Есть-то они есть, но. Если не хочется рукодельщины, то напрашивается использовать BOOST_PP_VARIADIC_xxxxx, а я не знаю, как свежий (или несвежий) буст поддерживает 2010 студию в этом вопросе. Тогда как SEQ поддерживается стопудов.

Вот чисто для примера, проблема на ровном месте. Ubuntu 12.04 LTS, официальная репа, метапакеты gcc и boost: gcc 4.6.3 (не поддерживает С++11), буст 1.46 (BOOST_PP_VARIADIC в виде заглушки).
Перекуём баги на фичи!
Re[6]: доступ к полям с помощью шаблона
От: Abyx Россия  
Дата: 06.02.13 19:06
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вот чисто для примера, проблема на ровном месте. Ubuntu 12.04 LTS, официальная репа, метапакеты gcc и boost: gcc 4.6.3 (не поддерживает С++11), буст 1.46 (BOOST_PP_VARIADIC в виде заглушки).

а еще говорят в никсах программировать удобно
In Zen We Trust
Re[7]: доступ к полям с помощью шаблона
От: Кодт Россия  
Дата: 06.02.13 20:38
Оценка:
Здравствуйте, Abyx, Вы писали:

К>>Вот чисто для примера, проблема на ровном месте. Ubuntu 12.04 LTS, официальная репа, метапакеты gcc и boost: gcc 4.6.3 (не поддерживает С++11), буст 1.46 (BOOST_PP_VARIADIC в виде заглушки).

A>а еще говорят в никсах программировать удобно

Угу. Это ж дебьян, те ещё консерваторы.
Вот, думаю, — поставить себе двух гусей (из канонической репы и из свежайшего) и потом следить, чтобы вызывалось то, что надо, а не то, что попало? Или пользоваться онлайн-компиляторами наподобие LWS для разных proof-of-concept, а локально — по старинке, оставатся в рамках gnu++0x.
Перекуём баги на фичи!
Re[4]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 07.02.13 07:11
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

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


DD>>>Объявить поля public Или речь идет о создании только RO доступа?

P>>Публичные поля это ересь, так учит нас Страуструп.

EP>Кто тебе это сказал?


EP>http://www.artima.com/intv/goldilocks2.html

EP>

EP>Bjarne Stroustrup: Going to the big class hierarchy is again, you write more code than you need to, and you get too much connection between different parts. I particularly dislike classes with a lot of get and set functions. That is often an indication that it shouldn't have been a class in the first place. It's just a data structure. And if it really is a data structure, make it a data structure.
EP>My rule of thumb is that you should have a real class with an interface and a hidden representation if and only if you can consider an invariant for the class.

EP>Bill Venners: What do you mean by invariant?

EP>Bjarne Stroustrup: What is it that makes the object a valid object? An invariant allows you to say when the object's representation is good and when it isn't. Take a vector as a very simple example. A vector knows that it has n elements. It has a pointer to n elements. The invariant is exactly that: the pointer points to something, and that something can hold n elements. If it holds n+1 or n-1 elements, that's a bug. If that pointer is zero, it's a bug, because it doesn't point to anything. That means it's a violation of an invariant. So you have to be able to state which objects make sense. Which are good and which are bad. And you can write the interfaces so that they maintain that invariant. That's one way of keeping track that your member functions are reasonable. It's also a way of keeping track of which operations need to be member functions. Operations that don't need to mess with the representation are better done outside the class. So that you get a clean, small interface that you can understand and maintain.

EP>Bill Venners: So the invariant justifies the existence of a class, because the class takes the responsibility for maintaining the invariant.

EP>Bjarne Stroustrup: That's right.

EP>Bill Venners: The invariant is a relationship between different pieces of data in the class.

EP>Bjarne Stroustrup: Yes. If every data can have any value, then it doesn't make much sense to have a class. Take a single data structure that has a name and an address. Any string is a good name, and any string is a good address. If that's what it is, it's a structure. Just call it a struct. Don't have anything private. Don't do anything silly like having a hidden name and address field with get_name and set_address and get_name and set_name functions. Or even worse, make a virtual base class with virtual get_name and set_name functions and so on, and override it with the one and only representation. That's just elaboration. It's not necessary.


А раньше он не так говорил. Укатали сивку крутые горки...

На самом деле открытые члены неудобны, так как к ним нельзя обращаться в шаблонах по типу.
Функции get в этом смысле гораздо удобнее и правильнее.
Re: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 07.02.13 07:53
Оценка:
P>Спасибо.

В продолжении темы: попробовал создать функции get с помощью шаблонов.


template<class T>
class b{
T val;
public:
b(T v):val(v){}
void get(T* v){*v=val;}
};

class a: public b<char>, public b<int>, public b<float> {
public:
a(char c,int i,float f):b<char>(c),b<int>(i),b<float>(f){}
};

main(){

a<char,int,float> aa(1,2,3);

char field1;
int field2;
float field3;
aa.get(&field1);
aa.get(&field2);
aa.get(&field3);
cout<<"\nfield1="<<(int)field1;
cout<<"\nfield2="<<field2;
cout<<"\nfield3="<<field3;
 
}


На такой код MSVC2010 ругается, говорит что конфликт функций get.

Вместе с тем такой код:


class a{

char  field1;
int   field2;
float field3;

public:

a(char c,int i,float f):field1(c),field2(i),field3(f){}

void get(char* v){*v=field1;}
void get(int* v){*v=field2;}
void get(float* v){*v=field3;}

};

int main(int argc,char* argv[]){

a aa(1,2,3);

char field1;
int field2;
float field3;
aa.get(&field1);
aa.get(&field2);
aa.get(&field3);
cout<<"\nfield1="<<(int)field1;
cout<<"\nfield2="<<field2;
cout<<"\nfield3="<<field3;

}


Транслируется.

Вопрос:

1. Почему при автоматической генерации функций get из шаблонов разного типа инстанцирования между ними конфликт, а если те же самые функции get написать руками, то конфликта нет?

Спасибо
Re[2]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 07.02.13 09:04
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>>Спасибо.


P>В продолжении темы: попробовал создать функции get с помощью шаблонов.


P>


P>main(){

P>a<char,int,float> aa(1,2,3);



Извиняюсь, тут должно быть


main(){

a aa(1,2,3);


Просто был еще вариант


template<class T1,class T2,class T3>
class a: public b<T1>, public b<T2>, public b<T3> {
public:
a(char c,int i,float f):b<T1>(c),b<T2>(i),b<T3>(f){}
};


Этот вариант тоже не транслируется с диагностикой "конфликт функций get".
Re[5]: доступ к полям с помощью шаблона
От: Evgeny.Panasyuk Россия  
Дата: 07.02.13 09:19
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>А раньше он не так говорил.


Пруф?

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


"На самом деле руки не удобны, так как на них нельзя поставить самосвал"

P>Функции get в этом смысле гораздо удобнее и правильнее.


Как уже говорили ранее, тебе нужен Boost.Fustion, а в частности set:
typedef set<int, float> S;
S s(12, 5.5f);
std::cout << at_key<int>(s) << std::endl;
std::cout << at_key<float>(s) << std::endl;
std::cout << result_of::has_key<S, double>::value << std::endl;
Re[2]: доступ к полям с помощью шаблона
От: Evgeny.Panasyuk Россия  
Дата: 07.02.13 09:23
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>1. Почему при автоматической генерации функций get из шаблонов разного типа инстанцирования между ними конфликт, а если те же самые функции get написать руками, то конфликта нет?


добавь в класс a:
using b<char>::get;
using b<int>::get;
using b<float>::get;
Re[6]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 07.02.13 10:36
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

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


P>>А раньше он не так говорил.


EP>Пруф?


Да пожалуйста, у нас это как отче наш:


http://lib.ru/CPPHB/cpptut.txt

— Определяйте интерфейс так, чтобы открывать минимальное количество
требуемой информации:
- Используйте, всюду где это можно, частные данные и функции-члены.
— Используйте описания public или protected, чтобы отличить
запросы разработчика производных классов от запросов обычных
пользователей.


И еще в других разных местах, например:


http://lib.web-malina.com/getbook.php?bid=4536&amp;page=5

Правила Правой Руки (*)

Здесь приводится набор правил, которых вам хорошо бы
придерживаться изучая C++. Когда вы станете более опытны, вы можете
превратить их в то, что будет подходить для вашего рода
деятельности и вашего стиля программирования. Они умышленно сделаны
очень простыми, поэтому подробности в них опущены. Не воспринимайте
их чересчур буквально. Написание хороших программ требует ума,
вкуса и терпения. Вы не собираетесь как следует понять это с самого
начала; поэкспериментируйте!
[1] Когда вы программируете, вы создаете конкретное
представление идей вашего решения некоторой задачи. Пусть
структура отражает эти идеи настолько явно, насколько это
возможно:
[1] Если вы считате "это" отдельным понятием, сделайте его
классом.

____________________
(*) Некоторые легко запоминаемые эмпирические правила, "Правила-
помошники." (прим. перев.)

— стр 18 —

[2] Если вы считате "это" отдельным объектом, сделайте его
объектом некоторого класса.
[3] Если два класса имеют общим нечто существенное, сделайте
его базовым классом. Почти все классы в вашей программе
будут иметь нечто общее; заведите (почти) универсальный
базовый класс, и разработайте его наиболее тщательно.
[2] Когда вы определяете класс, который не реализует
некоторый математический объект, вроде матрицы или
комплексного числа, или тип низкого уровня, вроде связанного
списка, то:
[1] Не используйте глобальные данные.
[2] Не используйте глобальные функции (не члены).
[3] Не используйте открытые данные-члены.
[4] Не используйте друзей, кроме как чтобы избежать [a], [b]
или [c].
[5] Не обращайтесь к данным-членам или другим объектам
непосредственно.
[6] Не помещайте в класс "поле типа"; используйте виртуальные
функции.
[7] Не используйте inline-функции, кроме как средство
существенной оптимизации.

Re[3]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 07.02.13 14:09
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

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


P>>1. Почему при автоматической генерации функций get из шаблонов разного типа инстанцирования между ними конфликт, а если те же самые функции get написать руками, то конфликта нет?


EP>добавь в класс a:

EP>
EP>using b<char>::get;
EP>using b<int>::get;
EP>using b<float>::get;
EP>


Прикольно.

На Borland C++ Builder транслируется, но не работает (достает ерунду вместо значений 1,2,3).
На MSVC 2010 транслируется и работает.
Вариант без шаблона транслируется и работает и там и там.
Re: доступ к полям с помощью шаблона
От: akochnev Россия  
Дата: 08.02.13 07:32
Оценка:
Здравствуйте, pepsicoca, Вы писали:
P>1. Как быть и что делать? Неужели нужно писать вручную все функции доступа к полям?

class Foo
{
public:
    char  field1;
    int   field2;
    float field3;
public:
    template<typename T, typename F>
    T get(T F::*field) const
    {
        return this->*field;
    }
};

std::cout << foo.get(&Foo::field1) << std::endl;

Не нравиться тут упоминание имени класса.
Можно объявить глобальную переменную
const char Foo::*field1 = &Foo::field1;

и использовать

std::cout << foo.get(field1) << std::endl;
Re[2]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 08.02.13 09:52
Оценка:
Здравствуйте, akochnev, Вы писали:

Идея кудрявая, но:

1. Смущают открытые поля field.
2. Смущает передача параметра в функцию по значению. Это уменьшает производительность, особенно если поле большое.
3. Смущает возврат параметра из функции по значению. Это уменьшает производительность, особенно если поле большое.
4. Хотелось бы получать из функции указатель на поле и передавать в нее хотя бы указатель на поле. Но пока максимум того, что у меня получилось это передать значение и получить указатель:


    template<typename T, typename F>
    T* get1(T F::*field) 
    {
        return &(this->*field);
    }


В идеале надо бы ничего не передавать вообще.
Re[3]: доступ к полям с помощью шаблона
От: akochnev Россия  
Дата: 08.02.13 12:08
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>Идея кудрявая, но:


P>1. Смущают открытые поля field.

меня тоже

P>2. Смущает передача параметра в функцию по значению. Это уменьшает производительность, особенно если поле большое.

В геттер передается только указатель на член класса.

P>3. Смущает возврат параметра из функции по значению. Это уменьшает производительность, особенно если поле большое.

Можно возвращать ссылку, проблем не вижу
template<typename T, typename F>
const T& get(T F::*field) const
{
    return this->*field;
}


P>4. Хотелось бы получать из функции указатель на поле и передавать в нее хотя бы указатель на поле. Но пока максимум того, что у меня получилось это передать значение и получить указатель:

template<typename T, typename F>
void get(F field, T& result) const
{
    result = this->*field;
}


P>В идеале надо бы ничего не передавать вообще.

Так не получится сделать, потому что это подразумевает у класса функции, которые отличаются только типом возвращаемого значения

Я бы посоветовал вообще избегать делать что-то подобное в коде, то есть очевидную задачу решать не очевидным путем.
Тем более что большинство IDE умеют автоматически генерить геттеры и сеттеры.
Re[4]: доступ к полям с помощью шаблона
От: pepsicoca  
Дата: 08.02.13 12:12
Оценка:
P>>2. Смущает передача параметра в функцию по значению. Это уменьшает производительность, особенно если поле большое.
A>В геттер передается только указатель на член класса.

В геттер передается объект типа T. То есть либо char, либо int, либо float (в примере).
Если тип T не такой маленький, а побольше, то...
Re[3]: доступ к полям с помощью шаблона
От: Erop Россия  
Дата: 08.02.13 13:22
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>В идеале надо бы ничего не передавать вообще.


А как ты хотел бы задавать гуттеры?..
Но номеру поля, по элементу перечисления, как-то ещё?..

Собственно всё упирается в два аспекта.
1) Как задавать геттеры
2) Как представлять список полей, к которым нужны геттеры?

Один путь -- заводим специальные шаблоны типов, заворачивающих поля. Ну, то есть, есть такой шаблон вроде
template<typename T>class CFieldWithGetter {
public:
    CFieldWithGetter();
//    CFieldWithGetter( const CFieldWithGetter& other ) : body( other.body ) {}
    template<typename T1>
    CFieldWithGetter( const T1& a1 ) : body( a1 ) {}
    template<typename T1, typename T2>
    CFieldWithGetter( const T1& a1, const T2& a2 ) : body( a1, a2 ) {}
    //  и т. д.

    void swap( T& other ) { std::swap( body, other ); }
    void swap( CFieldWithGetter& other ) { std::swap( body, other.body ); }

    // В принципе вместо этого можено сеттер написать
    void opearator = ( const T& other ) { body = other; }
    void opearator = ( const CFieldWithGetter& other ) { body = other.body; }

    //  Внимание!!! Всё ради этого!!!
    const T& Get() const { return body; }
private:
    T body;
};
ну и фигачишь свою структурку в виде:
struct MyData {
    CFieldWithGetter<int> field_1;
    CFieldWithGetter<char> field_1;
    CFieldWithGetter<std::string> field_1;
};
или гуглишь что-то вроде "свойства для C++", можно прямо на КЫВТе

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

В общем напиши кусок клиентского кода, как бы ты хотел, чт бы всё было, когда всё будет.
И можно будет что-то предложить
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: доступ к полям с помощью шаблона
От: serjjj Россия  
Дата: 10.02.13 21:44
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>Публичные поля это ересь, так учит нас Страуструп.


Если говорить о классах, то все верно. Но что бы структура стала классом не достаточно просто подписать слово "class" вначале. Необходимо выполнить некоторые условия. Так если есть много полей и нет особой логики работы с ними, то это скорее всего структура. Лучше сделать "структуру с конструктором", и не париться такими искусственно созданными проблемами.
Re[3]: доступ к полям с помощью шаблона
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 11.02.13 10:24
Оценка:
Здравствуйте, Kernan, Вы писали:

A>>это называется std::tuple, или boost::fusion, в зависимости от того что вы с этими полями собираетесь делать.

K>А это назвается из пушки по воробьям .
Минусующие, вы хотя бы примерчик с fusion написали перед тем, как минус ставить. Тупл не интересует.
Sic luceat lux!
Re[7]: доступ к полям с помощью шаблона
От: Evgeny.Panasyuk Россия  
Дата: 11.02.13 18:01
Оценка:
Здравствуйте, pepsicoca, Вы писали:

P>>>А раньше он не так говорил.

EP>>Пруф?
P>Да пожалуйста, у нас это как отче наш:
P>

P>http://lib.ru/CPPHB/cpptut.txt


"Второе дополненное издание" As C++ evolved, a second edition was published in July <b>1991</b>


P>И еще в других разных местах, например:

P>

P>http://lib.web-malina.com/getbook.php?bid=4536&amp;page=5


А это вообще походу первое The first edition of The C++ Programming Language was published in <b>1985</b>


P>

P> Правила Правой Руки (*)
P> Здесь приводится набор правил, которых вам хорошо бы
P>придерживаться изучая C++. Когда вы станете более опытны, вы можете
P>превратить их в то, что будет подходить для вашего рода
P>деятельности и вашего стиля программирования. Они умышленно сделаны
P>очень простыми, поэтому подробности в них опущены. Не воспринимайте
P>их чересчур буквально. Написание хороших программ требует ума,
P>вкуса и терпения. Вы не собираетесь как следует понять это с самого
P>начала; поэкспериментируйте!

P> [2] Когда вы определяете класс, который не реализует
P> некоторый математический объект, вроде матрицы или
P> комплексного числа, или тип низкого уровня, вроде связанного
P> списка, то:
P> [3] Не используйте открытые данные-члены.


Ключевое слово — класс. Если все поля объекта, может прочитать/изменить кто-угодно, напрямую или через getters&setters то это структура, а не класс, так тут нет никаких инвариантов (а если есть — то значит любой может mess with it).

The C++ Programming Language Third Edition:

10.2.8 Structures and Classes [class.struct]
...
Which style you use depends on circumstances and taste. I usually prefer to use struct for classes
that have all data public
. I think of such classes as ‘‘not quite proper types, just data structures.’’

,

10.5 Advice [class.advice]
Use public data (structs) only when it really is just data and no invariant is meaningful for the
data members
; §10.2.8.

Re: доступ к полям с помощью шаблона
От: Vamp Россия  
Дата: 11.02.13 18:40
Оценка:
P>Нужен доступ к полям класса.
P>Каждый раз писать новую функцию getX не хочется.
Сделать поля public.
Да здравствует мыло душистое и веревка пушистая.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.