SRC: auto_value<>
От: Кодт Россия  
Дата: 16.01.03 12:10
Оценка: 207 (25) +1
Вот, достало ловить ошибки с неинициализованными членами больших классов, вида
class MyBigClass
{
  int m_mySmallValue;
  ...

  MyBigClass();
  MyBigClass(X x, Y y, Z z);
  ... и еще куча конструкторов

};

MyBigClass::MyBigClass(xxxx) : ......
  // а про малюсенькое данное забыли :(
{
}


Поэтому сделал шаблон самоинициализирующихся значений простых типов (числа, указатели).
template< class T, T i = 0 >
class auto_value
{
  T t_;
public:
  typedef T data_t;
  typedef auto_value& self_t;

  // конструктор по умолчанию - главное достоинство этой тулзы
  inline auto_value() : t_(i) {}

  // конструктор с 1 параметром (в том числе - конструктор копирования)
  template< class V >
  inline auto_value(V v) : t_(v) {}

  // доступ к данному
  inline const T& data() const { return t_; }
  inline T& data() { return t_; }

  // считается, что исходный тип - простой
  inline operator T  () const { return t_; }
  inline operator T& ()       { return t_; }

  // операторы присваивания
  template< class V > inline self_t operator =   (V v) { t_ =   v; return *this; }
  template< class V > inline self_t operator +=  (V v) { t_ +=  v; return *this; }
  template< class V > inline self_t operator -=  (V v) { t_ -=  v; return *this; }
  template< class V > inline self_t operator *=  (V v) { t_ *=  v; return *this; }
  template< class V > inline self_t operator /=  (V v) { t_ /=  v; return *this; }
  template< class V > inline self_t operator %=  (V v) { t_ %=  v; return *this; }
  template< class V > inline self_t operator &=  (V v) { t_ &=  v; return *this; }
  template< class V > inline self_t operator |=  (V v) { t_ |=  v; return *this; }
  template< class V > inline self_t operator ^=  (V v) { t_ ^=  v; return *this; }
  template< class V > inline self_t operator <<= (V v) { t_ <<= v; return *this; }
  template< class V > inline self_t operator >>= (V v) { t_ >>= v; return *this; }
};

Такая куча операторов ??= нужна, чтобы не писать постоянно "myvalue.data() ??= 123"

Пример использования:
class MyBigClass
{
  auto_value<bool /* , false */ > m_bEnabled;
  ...

public:
  MyBigClass() {} // все члены инициализируются сами - как сумеют
  ...
  bool isEnabled() { return m_bEnabled; } // получим false, а не 0xCDCDCDCD
  void setEnabled(bool b) { m_bEnabled = b; }
  ...
};
Перекуём баги на фичи!
Re: SRC: auto_value<>
От: comer США http://getboost.codeplex.com/
Дата: 16.01.03 12:37
Оценка:
Здравствуйте, Кодт, Вы писали:

К>
...
К>  inline operator T  () const { return t_; }
...
К>


Может лучше будет?
inline operator T const &() const { return t_; }


К>  // операторы присваивания

А как же все остальные? сравнение, сложение, сдвиги, инкрементация и т.п. и т.д.?
getboost.codeplex.com
citylizard.codeplex.com
Re[2]: SRC: auto_value<>
От: Atilla Россия  
Дата: 16.01.03 12:42
Оценка:
Здравствуйте, comer, Вы писали:

C>А как же все остальные? сравнение, сложение, сдвиги, инкрементация и т.п. и т.д.?


это для простеньких-то типов (int, char, void*) ?
... << RSDN@Home 1.0 beta 4 >>
Кр-ть — с.т.
Re[2]: SRC: auto_value<>
От: Кодт Россия  
Дата: 16.01.03 13:07
Оценка: +1
Здравствуйте, comer, Вы писали:

К>>  inline operator T  () const { return t_; }


C>Может лучше будет?

C>inline operator T const &() const { return t_; }

Заведомо не лучше. Невозможно будет использовать неявное преобразование типов.
Больше того, даже форма
  inline operator const T& () const { return t_; }

приведет к неоднозначности и куче матов со стороны компилятора (проверял на VC 6sp5, GCC 2.7.2).

C>
К>>  // операторы присваивания
C>

C>А как же все остальные? сравнение, сложение, сдвиги, инкрементация и т.п. и т.д.?

Если определен operator T() const
то нужда у них отпадает.

Про инкремент — да, забыл.
Добавляю
  inline self_t operator ++ ()    { ++t_; return *this; } // префиксный
  inline data_t operator ++ (int) { return t_++; } // постфиксный

аналогично — для декремента.
Перекуём баги на фичи!
Re: SRC: auto_value<>
От: Кодт Россия  
Дата: 16.01.03 18:14
Оценка:
Дополнение
К>template< class T, T i = 0 >
К>class auto_value


Обычное применение этого шаблона — простые типы, передаваемые по значению. Поэтому параметр "i" оставлен того же типа, что и поле данных.

Однако, если есть большая нужда в приведении типов, то легко расширить шаблон:
template< class T, class I = T, I i = 0 >
class auto_value_ex
{
  .....
};


Если определить auto_value через auto_value_ex,
template< class T, T i = 0 >
class auto_value : public auto_value_ex< T, T, i >
{
  .....
};

то придется затащить в него все конструкторы и, вероятно, операторы. Поменяется шило на мыло.
Перекуём баги на фичи!
Re[3]: SRC: auto_value<>
От: comer США http://getboost.codeplex.com/
Дата: 16.01.03 18:18
Оценка:
Здравствуйте, Кодт, Вы писали:

К>
C>>inline operator T const &() const { return t_; }
К>

К>Заведомо не лучше. Невозможно будет использовать неявное преобразование типов.

Проверял на GCC 3.1. Там все нормально. Проходит без ругательств. В том числе и неявное преобразование типов с операторами возвращающими ссылку на константу. Вообще то я не совсем понимаю, почему не проходит неявное преобразование с ссылками на константы, а с обычными проходит? Приведи пример, пожалуйста. Просто я стараюсь делать как можно более похожие интерфейсы функций/операторов для константного и неконстантного объекта. Привычка.

К>Если определен operator T() const

К>то нужда у них отпадает.
Угу. Сорри.
getboost.codeplex.com
citylizard.codeplex.com
Re[3]: SRC: auto_value<>
От: comer США http://getboost.codeplex.com/
Дата: 16.01.03 18:33
Оценка:
Здравствуйте, Кодт, Вы писали:

К>
C>>inline operator T const &() const { return t_; }
К>

К>Заведомо не лучше. Невозможно будет использовать неявное преобразование типов.

И еще. Вот с таким оператором,
operator T const &() const;


можно написать так:
auto_value<int, 3> const a;
int const &b = a;


С таким
operator T() const;


уже так не напишешь.
getboost.codeplex.com
citylizard.codeplex.com
Re[3]: SRC: auto_value<>
От: comer США http://getboost.codeplex.com/
Дата: 16.01.03 18:35
Оценка:
Здравствуйте, Atilla, Вы писали:

C>>А как же все остальные? сравнение, сложение, сдвиги, инкрементация и т.п. и т.д.?

A>это для простеньких-то типов (int, char, void*) ?
А зачем их дискриминировать? Чем они хуже?
getboost.codeplex.com
citylizard.codeplex.com
Re[4]: SRC: auto_value<>
От: Кодт Россия  
Дата: 16.01.03 18:47
Оценка:
Здравствуйте, comer, Вы писали:

C>>>inline operator T const &() const { return t_; }

К>>Заведомо не лучше. Невозможно будет использовать неявное преобразование типов.

C>Проверял на GCC 3.1. Там все нормально. Проходит без ругательств. В том числе и неявное преобразование типов с операторами возвращающими ссылку на константу. Вообще то я не совсем понимаю, почему не проходит неявное преобразование с ссылками на константы, а с обычными проходит? Приведи пример, пожалуйста. Просто я стараюсь делать как можно более похожие интерфейсы функций/операторов для константного и неконстантного объекта. Привычка.


У меня тоже эта привычка. Однако такой пример:

Если определить оператор "значение" как
operator const T&() const
то имеем ошибки на всех операциях над значением: (компилятор VC6sp5)
class CChannel ...
{
  ...
  auto_value<bool> m_bEnabled;
  ...
public:
  STDMETHOD(notifyReceiver)()
  {
    if( !m_bEnabled )
// error C2675: unary '!' :
// 'class auto_value<bool,0>' does not define this operator or a conversion to a type
// acceptable to the predefined operator
      ...
  }
  ...
};

а если — как
operator T() const
, то не имеем.

Впрочем, можно определить оба варианта:
  operator T () const { return t_; }
  operator const T& () const { return t_; }
  operator T& () { return t_; }

(может быть, где-то в другом месте вылезет ambiguous call).
А пока я добавил эту тулзу вот с этими тремя операторами в большой проект, и надеюсь поиметь отзывы от сотрудников в течение недели.
Перекуём баги на фичи!
Re[5]: SRC: auto_value<>
От: comer США http://getboost.codeplex.com/
Дата: 16.01.03 19:29
Оценка:
Здравствуйте, Кодт, Вы писали:


К>У меня тоже эта привычка. Однако такой пример:

К>
К>...
К>    if( !m_bEnabled )
К>...
К>

Как обычно, во всем виноват MS. GCC 3.1 нормально компилирует нечто подобное.

К>Впрочем, можно определить оба варианта:

К>
К>  operator T () const { return t_; }
К>  operator const T& () const { return t_; }
К>  operator T& () { return t_; }
К>

К>(может быть, где-то в другом месте вылезет ambiguous call).
К>А пока я добавил эту тулзу вот с этими тремя операторами в большой проект, и надеюсь поиметь отзывы от сотрудников в течение недели.

Кстати, если объявлены два таких оператора
inline operator T const &() const { return t_; }
inline operator T () const { return t_; }

то GCC 3.1, не может откомпилировать вот это:

auto_value<bool> b;
!b;

Если только один любой из них, то может.

Так что:
    inline operator T const &() const { return t_; }
#ifdef _MSC_VER 
    inline operator T() const { return t_; }  
#endif


Интересно, кстати, какой из этих операторов в таком случае будет использовать VC?
getboost.codeplex.com
citylizard.codeplex.com
Re[6]: SRC: auto_value<>
От: Кодт Россия  
Дата: 16.01.03 19:38
Оценка:
Здравствуйте, comer, Вы писали:

C>Кстати, если объявлены два таких оператора

C>
C>inline operator T const &() const { return t_; }
C>inline operator T () const { return t_; }  
C>

C>то GCC 3.1, не может откомпилировать вот это:

Екандыбабай! А GCC 2.7.2 — сожрал (да, старый, да, кривой... но единственно доступный для целевой платформы).

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

А безшаблонный вариант, интересно, как себя ведет?
Еще можно на Comeau-online проверить, но это — позже.

C>Интересно, кстати, какой из этих операторов в таком случае будет использовать VC?


Достаточно воткнуть трассирову, или же Александеску'вские compile-time check.
Перекуём баги на фичи!
Re[2]: SRC: auto_value<>
От: Andrew S Россия http://alchemy-lab.com
Дата: 16.01.03 22:33
Оценка:
Возможно, я скажу глупость, но я бы использовал template < class T, T i = T() >
что дает таки большую свободу в типах, нежели инициализирование нулем.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: SRC: auto_value<>
От: MaximE Великобритания  
Дата: 16.01.03 22:47
Оценка:
Здравствуйте, Кодт, Вы писали:

К>
К>  // доступ к данному
К>  inline const T& data() const { return t_; }
К>


Саттер и ISO/IEC 14882 пишут, что функция вида:
T f();

где T является встроенным типом, всегда возвращает r-value. cv-квалифиатор не может быть применен к r-value, и это может помешать инстанцированию шаблонов.
Т.е., чтобы это было совсем корректно, возможно, придется воспользоваться type traits.
Re[2]: SRC: auto_value<>
От: Кодт Россия  
Дата: 17.01.03 08:43
Оценка:
Здравствуйте, MaximE, Вы писали:

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


К>>
К>>  // доступ к данному
К>>  inline const T& data() const { return t_; }
К>>


ME>Саттер и ISO/IEC 14882 пишут, что функция вида:

ME>
ME>T f();
ME>

ME>где T является встроенным типом, всегда возвращает r-value. cv-квалифиатор не может быть применен к r-value, и это может помешать инстанцированию шаблонов.
ME>Т.е., чтобы это было совсем корректно, возможно, придется воспользоваться type traits.

И именно поэтому я пишу не T data() const, а const T& data() const.
Чтобы получить константное l-value (и в дальнейшем, например, использовать указатель на константу:
auto_value<int> x;

const int *y = & x.data();
Перекуём баги на фичи!
Re[3]: SRC: auto_pod<>
От: Кодт Россия  
Дата: 17.01.03 08:54
Оценка:
Здравствуйте, Andrew S, Вы писали:

AS>Возможно, я скажу глупость, но я бы использовал template < class T, T i = T() >

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

Вопрос: int() == 0?

А вообще, можно же сделать шаблон для инициализации POD-структур .
template< class POD >
struct auto_pod : public POD
{
  auto_pod() { memset( static_cast<POD*>(this), 0, sizeof(POD) ); }
};

(тут нужно быть аккуратным с пустыми структурами, т.к. их sizeof() == 1).
Перекуём баги на фичи!
Re[4]: SRC: auto_pod<>
От: Andrew S Россия http://alchemy-lab.com
Дата: 17.01.03 08:58
Оценка:
К>Вопрос: int() == 0?

Как я помню — да. Значение по умолчанию для int — 0. запись вида int i = int(); инициализирует переменную значением по умолчанию.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: SRC: auto_value<>
От: MaximE Великобритания  
Дата: 17.01.03 09:20
Оценка:
Здравствуйте, Кодт, Вы писали:

К>И именно поэтому я пишу не T data() const, а const T& data() const.

К>Чтобы получить константное l-value (и в дальнейшем, например, использовать указатель на константу:

Простите, облажался я . Не заметил &
Re[4]: SRC: auto_pod<>
От: Блудов Павел Россия  
Дата: 27.01.03 06:52
Оценка: 42 (1)
Здравствуйте, Кодт, Вы писали:

К>(тут нужно быть аккуратным с пустыми структурами, т.к. их sizeof() == 1).


Этот вопрос решается простым наследованием структуры с одним полем байтовой длины:

#define _offsetof(type, field)    ((int)&((type*)0)->field)

template< class POD >
struct auto_pod : public POD
{
  struct _PODSize : POD { char _Dummy; };

  auto_pod() { memset( static_cast<POD*>(this), 0, _offsetof(_PODSize, _PODSize::_Dummy)); }
};


Если POD без полей, то 1 == sizeof(POD), и 0 == _offsetof(_PODSize, _PODSize::_Dummy).

Интересный, кстати момент:

struct aa
{
    __int64    i1;
    __int8    i2;
};

16 == sizeof(aa);


Хотя в этом случае, нилем имеет смысл прописать только первые 9-ть байт.
Есть идеи?

Павел.
Re[5]: SRC: auto_pod<>
От: Кодт Россия  
Дата: 27.01.03 09:22
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

К>>(тут нужно быть аккуратным с пустыми структурами, т.к. их sizeof() == 1).


БП>Этот вопрос решается простым наследованием структуры с одним полем байтовой длины:


Супер!
БП>#define _offsetof(type, field)    ((int)&((type*)0)->field)

БП>template< class POD >
БП>struct auto_pod : public POD
БП>{
БП>  struct _PODSize : POD { char _Dummy; };

     inline static size_t sizeofpod() { return _offsetof(_PODSize, _PODSize::_Dummy); }

БП>  auto_pod() { memset( static_cast<POD*>(this), 0, sizeofpod()); }

     auto_pod(const POD& pod) { memcpy( static_cast<POD*>(this), &pod, sizeofpod() ); }

     void operator=(const POD& pod) { memcpy( static_cast<POD*>(this), &pod, sizeofpod() ); }
БП>};


БП>Если POD без полей, то 1 == sizeof(POD), и 0 == _offsetof(_PODSize, _PODSize::_Dummy).


Хотя было бы полезно написать шаблон приблизительно такого вида:
template< class T >
struct struct_traits
{
  .....
  enum { isNotEmptyPOD = ..... };
  .....

  template < bool b >
  class _auto_pod_impl : public T
  { };

  template <>
  class _auto_pod_impl<false> // cпециальная версия для структур с нулевым размером
  : public T // для возможности преобразования типов
  {
    _auto_pod_impl() {}
    _auto_pod_impl(const T&) {}
    void operator=(const T&) {}
  };

  typedef _auto_pod_impl< isNotEmptyPOD > auto_pod;
};

template< class T >
class auto_pod : struct_traits<T>::auto_pod
{ };


БП>Интересный, кстати момент:


БП>
БП>struct aa
БП>{
БП>    __int64    i1;
БП>    __int8    i2;
БП>};

БП>16 == sizeof(aa);
БП>


БП>Хотя в этом случае, нилем имеет смысл прописать только первые 9-ть байт.

БП>Есть идеи?

А пусть компилятор сам занимается этим. Он оптимизировал размер, пусть он же оптимизирует копирование.

(И вообще, memset/memcpy/memmove — это моветон. Проблема-то была — объехать баг VC).
Перекуём баги на фичи!
Re[6]: SRC: auto_pod<>
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 09.02.03 10:46
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Супер!

#define _offsetof(type, field)    ((int)&((type*)0)->field)

Такой код может быть написан только в реализации стандартной библиотеки, или в компиляторно-зависимой библиотеке. Для всего остального разыменование нулевого указателя не является легальным C++ (p->m => (*(p)).m (см. 5.2.5/3)).

Ну, и про идентификаторы тоже... Все, что начинается с _<Большая латинская> — зарезервировано.
Алексей Кирдин
Re[7]: SRC: auto_pod<>
От: Блудов Павел Россия  
Дата: 10.02.03 04:12
Оценка: :)
Здравствуйте, Kaa, Вы писали:

Kaa>разыменование нулевого указателя не является легальным C++ (p->m => (*(p)).m (см. 5.2.5/3)).


Для эстетов:

#define _offsetof(type, field)    (((int)&((type*)0xDEADBEEF)->field) - (int)0xDEADBEEF)


Работает точно так же. Прочитал внимательно 5.2.5 Class member access [expr.ref].
Ни слова о нулевом указателе. Нельзя ли подробнее, что же я упустил?

Kaa>Ну, и про идентификаторы тоже... Все, что начинается с _<Большая латинская> — зарезервировано.


Вы про auto_pod::_PODSize? Он начинается с маленькой латинской буквы.
Указанное Вами правило (17.4.3.1.2) относится только к глобальным именам.
Или у нас стандарты разные

Павел.
Re[8]: SRC: auto_pod<>
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 10.02.03 09:38
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

Kaa>>разыменование нулевого указателя не является легальным C++ (p->m => (*(p)).m (см. 5.2.5/3)).


БП>Прочитал внимательно 5.2.5 Class member access [expr.ref].

БП>Ни слова о нулевом указателе. Нельзя ли подробнее, что же я упустил?
1.9/4, к примеру, говорит, что разыменование нулевого указателя порождает неопределенное поведение.

БП>Указанное Вами правило (17.4.3.1.2) относится только к глобальным именам.

Нет, стандарты у нас одинаковые. Тут я не прав. Спасибо.
Алексей Кирдин
Re: SRC: auto_value<>
От: vt_vitus  
Дата: 15.11.03 12:05
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вот, достало ловить ошибки с неинициализованными членами больших классов, вида

... skip() ...
К>[/c]

А как можно модифицировать этот замечательный класс, что бы можно было писать нечто
    auto_value<int> i = 0;
    auto_value<int> j = i;

А то ругается на это, говорит : error C2440: 'initializing' : cannot convert from 'class auto_value<int,0>' to 'class auto_value<int,0>'
No copy constructor available for class 'auto_value<int,0>'

без этого в конструкторах копии приходится писать

CStructPath::CStructPath(const CStructPath& sp)/*:
startIndex(sp.startIndex)*/
{
    int i = sp.startIndex;
    startIndex = i;
//    finishIndex = sp.finishIndex;
//    bterminate = sp.bterminate;
//    bcreate = sp.bcreate;
}

ни одно из закомментаренных инициализаций не проходит ...
или я чего-то не так понял/сделал ?
Re[2]: SRC: auto_value<>
От: vt_vitus  
Дата: 15.11.03 12:42
Оценка:
не много облажался, как я понимаю надо так

CStructPath::CStructPath(const CStructPath& sp):
    startIndex(sp.startIndex.data())
{}


Но всё равно это не то ...
и ещё почему, на

auto_value<int> fI = 7;
int i = 5;
i = fI;

Вылетает ошибка — : error C2593: 'operator =' is ambiguous
Re[7]: SRC: auto_pod<>
От: MaximE Великобритания  
Дата: 15.11.03 14:04
Оценка:
Здравствуйте, Kaa, Вы писали:

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


К>>Супер!

Kaa>
Kaa>#define _offsetof(type, field)    ((int)&((type*)0)->field)
Kaa>


Kaa>Такой код может быть написан только в реализации стандартной библиотеки, или в компиляторно-зависимой библиотеке. Для всего остального разыменование нулевого указателя не является легальным C++ (p->m => (*(p)).m (см. 5.2.5/3)).


Он там и написан. <cstddef>:

#define offsetof(s,m)   (size_t)&(((s *)0)->m)


18.1.5
The macro offsetof accepts a restricted set of type arguments in this International Standard. type shall be a POD structure or a POD union (clause 9). The result of applying the offsetof macro to a field that is a static data member or a function member is undefined.

Re[8]: SRC: auto_pod<>
От: Kaa Украина http://blog.meta.ua/users/kaa/
Дата: 15.11.03 15:51
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Он там и написан. <cstddef>:

А еще — в коде Кодта Ключевое слово — "только". Так-что, все верно.
Алексей Кирдин
Re: SRC: auto_value<>
От: Рома Мик Россия http://romamik.com
Дата: 15.11.03 22:01
Оценка: -1
Здравствуйте, Кодт, Вы писали:

Сообщение старое, конечно. Но вот только что его прочитал. Кроме того янус еще не всю ветку у меня получил, так что, если что, не обижайтесь...

Я обычно с этой проблемой борюсь гораздо проще:
class Foo
{
    struct AllMyStaff
    {
        Bar bar;
        Foobar foobar;
        AllMyStaff() : bar( barParam ), foobar( foobarParam ) {}
    } allMyStaff;
};

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

А для легких, с конструктором по умолчанию, и которым присваивать можно:
class Foo
{
    Bar bar;
    Foobar foobar;
    struct AllMyStaff
    {
        AllMyStaff() 
        {
            bar = Bar(barParam);
            foobar = Foobar(foobarParam);
        }
    } allMyStaff;
};


Кроме того конструктор AllMyStaff ( хорошего названия я так и не придумал никогда, кто придумает скажите, а то уже надоели всякие X и прочие глупости ) можно сделать с параметром. Забыть его теперь нельзя, но можно передать нужные параметры.
... << RSDN@Home 1.1.0 stable >>
Re[2]: SRC: auto_value<>
От: Рома Мик Россия http://romamik.com
Дата: 15.11.03 22:15
Оценка:
Здравствуйте, Рома Мик, Вы писали:

Ну и уточнение. Совсем обычно я делаю так, как написано ниже, а написанное выше для случаев когда написанное ниже не годиться.
// .h
struct Foo
{
    //...
    static Foo * Make(FooParam);
};

//.cpp
namespace
{
    class FooInitializer
    {
        FooInitializer() {...};
    };
    class FooImpl : public Foo, private FooInitilizer
    {
    //...
    };
}
Foo * Foo::Make(FooParam)
{
    return new FooImpl(FooParam);
}
... << RSDN@Home 1.1.0 stable >>
Re[2]: SRC: auto_value<>
От: MaximE Великобритания  
Дата: 16.11.03 02:36
Оценка:
Здравствуйте, Рома Мик, Вы писали:

[]

РМ>А для легких, с конструктором по умолчанию, и которым присваивать можно:


РМ>
РМ>class Foo
РМ>{
РМ>    Bar bar;
РМ>    Foobar foobar;
РМ>    struct AllMyStaff
РМ>    {
РМ>        AllMyStaff() 
РМ>        {
РМ>            bar = Bar(barParam);
РМ>            foobar = Foobar(foobarParam);
        // a millon dollar question I did not have an answer to (© Max Payne 2)
        // чей bar и foobar?
РМ>        }
РМ>    } allMyStaff;
РМ>};
РМ>


Ты пробовал эту херню скомпилить хоть разок? Советую попробовать.
Re[3]: SRC: auto_value<>
От: Рома Мик Россия http://romamik.com
Дата: 16.11.03 12:45
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>Здравствуйте, Рома Мик, Вы писали:


ME>[]


РМ>>А для легких, с конструктором по умолчанию, и которым присваивать можно:


РМ>>
РМ>>class Foo
РМ>>{
РМ>>    Bar bar;
РМ>>    Foobar foobar;
РМ>>    struct AllMyStaff
РМ>>    {
РМ>>        AllMyStaff() 
РМ>>        {
РМ>>            bar = Bar(barParam);
РМ>>            foobar = Foobar(foobarParam);
ME>        // a millon dollar question I did not have an answer to (© Max Payne 2)
ME>        // чей bar и foobar?
РМ>>        }
РМ>>    } allMyStaff;
РМ>>};
РМ>>


ME>Ты пробовал эту херню скомпилить хоть разок? Советую попробовать.

Пробовал, но достаточно давно. Потому забыл подробности. Это довольно редко нужный код, т.к. редко нельзя унаследоваться от AllMyStaff. В этом варианте надо передавать this в конструктор AllMyStaff.
... << RSDN@Home 1.1.0 stable >>
Re[3]: SRC: auto_value<>
От: Кодт Россия  
Дата: 16.11.03 13:03
Оценка:
Здравствуйте, vt_vitus, Вы писали:

<>

Хотя я и использую auto_value в проекте, но давно туда руки не запускал.
Возможно, что нужно явно определить конструктор копирования
template<class V> auto_value(const V& v) : t_(v) {}
template<T j> auto_value(const auto_value<T,j>& v) : t_(v.data()) {}

Насчет операторов вида T *** auto_value<T>
затрудняюсь сказать.

Но, кстати, в примере ты написал auto_value<int> fI = 7;
а смысл?
Ведь его задача — обеспечивать конструирование вида auto_value<int,7> fI;
Перекуём баги на фичи!
Re[8]: SRC: auto_pod<>
От: Аноним  
Дата: 21.11.03 17:14
Оценка:
Здравствуйте, Блудов Павел, Вы писали:

[]
БП>
БП>#define _offsetof(type, field)    (((int)&((type*)0xDEADBEEF)->field) - (int)0xDEADBEEF)
БП>

[]

А чем плохо стандартное макро offsetof?
Re[5]: SRC: auto_pod<>
От: McSeem2 США http://www.antigrain.com
Дата: 02.12.03 18:02
Оценка:
БП>
БП>struct aa
БП>{
БП>    __int64    i1;
БП>    __int8    i2;
БП>};

БП>16 == sizeof(aa);
БП>


БП>Хотя в этом случае, нилем имеет смысл прописать только первые 9-ть байт.

БП>Есть идеи?

Нет никаких идей. Это — суровая правда жизни
struct aa
{
    __int8    i2;
    __int64    i1;
};

Здесь размер — тоже 16 и надо инициализировать все 16 байт. Как отличить эти два случая? Можно, конечно, тупо и грязно использовать #pragma pack, но на Intel это приведет к резкой деградации производительности, а на других платформах (Sun, SGI, если там есть аналогичная прагма) — вообще не будет работать, там сразу "автобусная ошибка" и до свидания...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: SRC: auto_value<>
От: _nn_ www.nemerleweb.com
Дата: 03.12.03 10:29
Оценка:
Здравствуйте, Кодт, Вы писали:

Очень хорошая идея , но имеет небольшой недостаток — переменный инициализируются полько в начале , а что если я хочу сбросить все переменные в начальное состояние ?

Есть решение но с использованием макросов:
template<class T, T i = T()>
class auto_value
{
  T t_;
public:
  typedef T data_t;
  typedef auto_value& self_t;
  // конструктор по умолчанию - главное достоинство этой тулзы
  inline auto_value() : t_(i) {}

  // конструктор с 1 параметром (в том числе - конструктор копирования)
  template< class V >
  inline auto_value(V v) : t_(v) {}

  // доступ к данному
  inline const T& data() const { return t_; }
  inline T& data() { return t_; }

  // считается, что исходный тип - простой
  inline operator T  () const { return t_; }
  inline operator T& ()       { return t_; }

  // операторы присваивания
  template< class V > inline self_t operator =   (V v) { t_ =   v; return *this; }
  template< class V > inline self_t operator +=  (V v) { t_ +=  v; return *this; }
  template< class V > inline self_t operator -=  (V v) { t_ -=  v; return *this; }
  template< class V > inline self_t operator *=  (V v) { t_ *=  v; return *this; }
  template< class V > inline self_t operator /=  (V v) { t_ /=  v; return *this; }
  template< class V > inline self_t operator %=  (V v) { t_ %=  v; return *this; }
  template< class V > inline self_t operator &=  (V v) { t_ &=  v; return *this; }
  template< class V > inline self_t operator |=  (V v) { t_ |=  v; return *this; }
  template< class V > inline self_t operator ^=  (V v) { t_ ^=  v; return *this; }
  template< class V > inline self_t operator <<= (V v) { t_ <<= v; return *this; }
  template< class V > inline self_t operator >>= (V v) { t_ >>= v; return *this; }

  // по умалчанию
  inline void default_() { t_=i; }
};

#define BEGIN_AUTO_MAP() \
    public: \
    void default_() \
    {

#define AUTO_VALUE(v) \
    v.default_();

#define END_AUTO_MAP() \
    }

class Test
{
 auto_value<int,5> i;
 auto_value<char,'a'> c;

 BEGIN_AUTO_MAP()
  AUTO_VALUE(i)
  AUTO_VALUE(c)
 END_AUTO_MAP()
};


void main()
{
 Test test;
 
 test.i=10;
 test.c='f';
 
 test.default_();
}


Есть другие решения ?

С Уважением.
NN.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: SRC: auto_value<>
От: MShura  
Дата: 09.01.04 22:48
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вот, достало ловить ошибки с неинициализованными членами больших классов


Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память.
Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.
Re[2]: SRC: auto_value<>
От: Кодт Россия  
Дата: 10.01.04 20:07
Оценка:
Здравствуйте, MShura, Вы писали:

MS>Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память.

MS>Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.

Во-первых, ты для каждого своего класса вынужден совершить ряд излишних телодвижений.
Во-вторых, не всегда это можно сделать — например, если я пишу кокласс с использованием ATL — там всегда используется единственный конструктор (без параметров) и к тому же класс заведомо не финальный: создается CComObject<MyClass> который является потомком.
Что же мне, ATL переписывать, чтобы там new память чистил?
Любая ситуация с наследованием от данного класса — и все, приплыли.
... << RSDN@Home 1.1.0 stable >>
Перекуём баги на фичи!
Re[3]: SRC: auto_value<>
От: MShura  
Дата: 11.01.04 19:41
Оценка:
Здравствуйте, Кодт, Вы писали:

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


MS>>Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память.

MS>>Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.

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

К>Во-вторых, не всегда это можно сделать — например, если я пишу кокласс с использованием ATL — там всегда используется единственный конструктор (без параметров) и к тому же класс заведомо не финальный: создается CComObject<MyClass> который является потомком.
К>Что же мне, ATL переписывать, чтобы там new память чистил?
К>Любая ситуация с наследованием от данного класса — и все, приплыли.

Насколько я помню, если оператор new есть у одного из базовых классов, то для производных он также будет вызываться (соответственно размер требуемой памяти будет передаваться нужный).
Re[3]: SRC: auto_value<>
От: MShura  
Дата: 11.01.04 19:47
Оценка: 15 (1)
Здравствуйте, Кодт, Вы писали:

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


MS>>Я для таких классов переопределяю оператор new, в котором обнуляю выделяемую память.

MS>>Все конструкторы переношу в private/protected и оставляю только статические функции типа CreateInstance с тем-же набором параметров, что и в конструкторах.

Это я делаю для классов, которыми могут пользоваться другие программисты. Таким образом я просто защищаюсь от создания экзампляра на стеке. Если наверняка известно, что данный класс ВСЕГДА будет создаваться с помощью оператора new (например в ATL/COM), то никаких лишиних телодвижений и не надо.
Забыл написать в прошлом посте, что у меня для этих целей есть простенький класс, у которого переопределены new + delete. Если мне нужна их функциональность, то я просто добавляю его в список базовых классов.
Re[4]: SRC: auto_value<>
От: Кодт Россия  
Дата: 11.01.04 21:22
Оценка:
Здравствуйте, MShura, Вы писали:

MS>Это я делаю для классов, которыми могут пользоваться другие программисты. Таким образом я просто защищаюсь от создания экзампляра на стеке. Если наверняка известно, что данный класс ВСЕГДА будет создаваться с помощью оператора new (например в ATL/COM), то никаких лишиних телодвижений и не надо.

MS>Забыл написать в прошлом посте, что у меня для этих целей есть простенький класс, у которого переопределены new + delete. Если мне нужна их функциональность, то я просто добавляю его в список базовых классов.

А если экземпляр — это член другого класса, тогда как быть? Тут не все так просто...
Кроме того, auto_value позволяет инициализировать переменные любым нужным значением
class Hello
{
    auto_value<bool,true> truth_;
    
    Hello() {}
    
    void goodbye() { truth_ = false; }
    
    bool came() const { return truth_; }
};
... << RSDN@Home 1.1.0 stable >>
Перекуём баги на фичи!
Re[5]: SRC: auto_value<>
От: MShura  
Дата: 12.01.04 08:34
Оценка:
Здравствуйте, Кодт, Вы писали:

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


MS>>Это я делаю для классов, которыми могут пользоваться другие программисты. Таким образом я просто защищаюсь от создания экзампляра на стеке. Если наверняка известно, что данный класс ВСЕГДА будет создаваться с помощью оператора new (например в ATL/COM), то никаких лишиних телодвижений и не надо.

MS>>Забыл написать в прошлом посте, что у меня для этих целей есть простенький класс, у которого переопределены new + delete. Если мне нужна их функциональность, то я просто добавляю его в список базовых классов.

К>А если экземпляр — это член другого класса, тогда как быть? Тут не все так просто...

А в чем проблема?Основное условие — все экземпляры/подэкземпляры должны создаваться через new.
Это так сказать цена за удобство.

К>Кроме того, auto_value позволяет инициализировать переменные любым нужным значением

Для таких целей тот подход бесполезен.
К>
К>class Hello
К>{
К>    auto_value<bool,true> truth_;
    
К>    Hello() {}
    
К>    void goodbye() { truth_ = false; }
    
К>    bool came() const { return truth_; }
К>};
К>
Re[6]: SRC: auto_value<>
От: Кодт Россия  
Дата: 12.01.04 11:19
Оценка:
Здравствуйте, MShura, Вы писали:

К>>А если экземпляр — это член другого класса, тогда как быть? Тут не все так просто...

MS>А в чем проблема?Основное условие — все экземпляры/подэкземпляры должны создаваться через new.
MS>Это так сказать цена за удобство.

Тебе не кажется, что каждый int на куче создавать — это дорогая цена?
Кроме того, такая утилитка
template<class T>
class pointer
{
  T* p;
public:
  pointer() : p(new T()) {}
  template<class V> pointer(const V& v) : p(new T(v)) {}
  pointer(const pointer<T>& ptr) : p(new T(*ptr)) {}

  ~pointer() { delete p; }

  T& operator*() { return *p; }
  const T& operator*() const { return *p; }

  T* operator->() { return p; }
  const T* operator->() const { return p; }
};

всегда будет инициализировать данные так как надо (вызывая конструктор без параметров).
И совершенно незачем химичить с new.
Перекуём баги на фичи!
Re[7]: SRC: auto_value<>
От: MShura  
Дата: 12.01.04 12:41
Оценка:
К>Тебе не кажется, что каждый int на куче создавать — это дорогая цена?

Вообще-то твой начальный пост содержал строку:
"Вот, достало ловить ошибки с неинициализованными членами больших классов, вида"

Я сказал, как я поступаю в таком случае. А теперь у тебя от большого класса остался только int?
Re[8]: SRC: auto_value<>
От: Кодт Россия  
Дата: 13.01.04 09:09
Оценка:
Здравствуйте, MShura, Вы писали:

MS>Вообще-то твой начальный пост содержал строку:

MS>"Вот, достало ловить ошибки с неинициализованными членами больших классов, вида"

MS>Я сказал, как я поступаю в таком случае. А теперь у тебя от большого класса остался только int?


Неинициализированные члены большого класса.
class SuperPuper
{
public:
  SuperPuper() : x_(10), y_(20), z_(30), yes_(true), no_(false), cancel_(false) {}
  SuperPuper(int x, int y, int z) : x_(x), y_(y), z_(z), yes_(true), no_(false), cancel_(false) {}
  SuperPuper(int ync) : x_(10), y_(20), z_(30), yes_(ync==0), no_(ync==1), cancel_(ync==2) {}

private:
  int x_;
  int y_;
  int z_;
  bool yes_, no_, cancel_;
  ...
  ...
  ...
  char c_; // добавили в новой версии, в конструкторы прописать забыли.
};

Для большого класса в любом случае существует конструктор, а порой и не один. Так что формально объект этого класса будет проинициализирован (а если нет конструктора без параметров — то компилятор еще и по пальцам надает за забывчивость) при включении его членом другого класса.
А вот для скалярных типов это действительно проблема.



Я еще раз хочу подчеркнуть: изыск возник как реальная потребность при разработке и сопровождении больших проектов.
Перекуём баги на фичи!
Re: SRC: auto_value<>
От: _nn_ www.nemerleweb.com
Дата: 20.04.04 08:34
Оценка:
Здравствуйте, Кодт, Вы писали:

Вот небольшое изменение от меня :
template<typename T>
class ExtractPtr
{
public:
    typedef T Type;
};

template<typename T>
class ExtractPtr<T*>
{
public:
    typedef T Type;
};

template<typename T,T t_init=0,T t_default=t_init>
class AutoValue
{
    T m_t;
public:
    // Constructor
    AutoValue() : m_t(t_init) {}
    template<class T2>
    AutoValue(T2& t) : m_t(t) {}

    // Data
    const T& Data() const { return m_t; }
    T& Data() { return m_t; }

    // Operators
    // T
    operator const T&() const { return m_t; }
    operator T&() { return m_t; }

    // Functor
    T& operator()() { return m_t; }
    const T& operator()() const { return m_t; }

    // Arithmetic
    template<typename T2> const AutoValue& operator=(const T2& t) { m_t=t; return *this; }
    template<typename T2> const AutoValue& operator+=(const T2& t) { m_t+=t; return *this; }
    template<typename T2> const AutoValue& operator-=(const T2& t) { m_t-=t; return *this; }
    template<typename T2> const AutoValue& operator*=(const T2& t) { m_t*=t; return *this; }
    template<typename T2> const AutoValue& operator/=(const T2& t) { m_t/=t; return *this; }
    template<typename T2> const AutoValue& operator%=(const T2& t) { m_t%=t; return *this; }
    template<typename T2> const AutoValue& operator&=(const T2& t) { m_t&=t; return *this; }
    template<typename T2> const AutoValue& operator|=(const T2& t) { m_t|=t; return *this; }
    template<typename T2> const AutoValue& operator^=(const T2& t) { m_t^=t; return *this; }
    template<typename T2> const AutoValue& operator<<=(const T2& t) { m_t<<=t; return *this; }
    template<typename T2> const AutoValue& operator>>=(const T2& t) { m_t>>=t; return *this; }

    // Compare
    template<typename T2> const bool operator==(const T2& t) const { return m_t==t; }
    template<typename T2> const bool operator!=(const T2& t) const { return m_t!=t; }
    template<typename T2> const bool operator>(const T2& t) const { return m_t>t; }
    template<typename T2> const bool operator>=(const T2& t) const { return m_t>=t; }
    template<typename T2> const bool operator<(const T2& t) const { return m_t<t; }
    template<typename T2> const bool operator<=(const T2& t) const { return m_t<=t; }

    // Increment , Decrement
    const AutoValue& operator++() { ++m_t; return *this; }
    const T& operator++(int) { return m_t++; }
    const AutoValue& operator--() { --m_t; return *this; }
    const T& operator--(int) { return m_t--; }

    // Pointers
    T* operator&() { return &m_t; }
    const T* operator&() const { return &m_t; }
    typename ExtractPtr<T>::Type& operator*() { return *m_t; }
    const typename ExtractPtr<T>::Type& operator*() const { return *m_t; }
    typename ExtractPtr<T>::Type& operator->() { return *m_t; }
    const typename ExtractPtr<T>::Type& operator->() const { return *m_t; }

    // Array
    T& operator[](int index) { return m_t[index]; }
    const T& operator[](int index) const { return m_t[index]; }

    // Functions
    void Reset() { m_t=t_default; }
};
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re: Навеяно auto_value<> ™ ( от Кодт )
От: Batiskaf Израиль http://www.mult.ru/
Дата: 10.10.04 11:26
Оценка:
Здравствуйте, Кодт, Вы писали:

С самого начала идея очень понравилась и немного развилась, давно практикую в своей работе такие вещи, вот решил поделиться мыслями:



class MyBigClass
{
  auto_value<bool /* , false */ > m_bEnabled;
  limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;
  ...

public:
  MyBigClass() {} // все члены инициализируются сами - как сумеют
  ...
  bool isEnabled() { return m_bEnabled; } // получим false, а не 0xCDCDCDCD
  void setEnabled(bool b) { m_bEnabled = b; }
  ...
};


В данном случае номер порта может присваиваться из определенного промежутка, в противном случае получите out_of_range.
Ну и имплементация limit достаточно проста:


template< typename T, size_t min, size_t max>
class limit : public T
{
    public:
    typedef T data_t;
    typedef limit& self_t;

    //default ctor
    inline limit() : T() {}

    // ctor with 1 parameter( including copy constructor)
    template< class V >
    inline limit(V v) : T(v) {}

    //access to data
    inline const T& data() const { return (T&)*this; }
    inline T& data() { return (T&)*this; }

    // means that original type is simple
    operator T () const { return data(); }
    operator const T& () const { return data(); }
    operator T& () { return data(); }

    //assignment operators
    template< class V > inline self_t operator =   (V v) 
    { 
        if( v < min || v > max )
            throw std::out_of_range("new value not in the range");
        data() = v;
        return *this; 
    }
    template< class V > inline self_t operator +=  (V v) 
    {
        T tmp = data();
        tmp +=  v; 
        *this = tmp;
        return *this; 
    }
    template< class V > inline self_t operator -=  (V v) 
    { 
        T tmp = data();
        tmp -=  v; 
        *this = tmp;
        return *this; 
    }
    template< class V > inline self_t operator *=  (V v) 
    { 
        T tmp = data();
        tmp *=  v; 
        *this = tmp;
        return *this; 
    }
    template< class V > inline self_t operator /=  (V v) 
    { 
        T tmp = data();
        tmp /=  v; 
        *this = tmp;
        return *this;
    }
    template< class V > inline self_t operator %=  (V v) 
    { 
        T tmp = data();
        tmp %=  v; 
        *this = tmp;
        return *this;
    }
    template< class V > inline self_t operator &=  (V v) 
    { 
        T tmp = data();
        tmp &=  v; 
        *this = tmp;
        return *this;
    }
    template< class V > inline self_t operator |=  (V v) 
    {     
        T tmp = data();
        tmp |=  v; 
        *this = tmp;
        return *this;
    }
    template< class V > inline self_t operator ^=  (V v) 
    {             
        T tmp = data();
        tmp ^=  v; 
        *this = tmp;
        return *this;
    }
    template< class V > inline self_t operator <<= (V v) 
    {             
        T tmp = data();
        tmp <<=  v; 
        *this = tmp;
        return *this;
    }
    template< class V > inline self_t operator >>= (V v) 
    {             
        T tmp = data();
        tmp >>=  v; 
        *this = tmp;
        return *this;
    }
    //prefix
    inline self_t operator ++ ()    
    { 
        T tmp = data();
        ++tmp;
        *this = tmp;
        return *this;
    }
    //postfix
    inline data_t operator ++ (int) 
    { 
        T tmp = data();
        tmp++; 
        *this = tmp;
        return data();
    }
};



Подобными требованиями-атрибутами можно нагрузить любые члены класса, речь идет не только о лимитах, к примеру можно проверять строку на присвоение пустой строки ( not_empty_string атрибут ), другие требования, которые больше относятся к бизнес логике приложения... Таким образом это завернутое поле запросто может выродиться в полноценное свойство, об отсутствии которых многие сегодня сетуют, тогда значительно упростится кодирование функциональности структур данных, все проверки значений полей сосредоточятся в одних местах.
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[2]: Навеяно auto_value<> ™ ( от Кодт )
От: _nn_ www.nemerleweb.com
Дата: 10.10.04 11:38
Оценка:
Здравствуйте, Batiskaf, Вы писали:

B>В данном случае номер порта может присваиваться из определенного промежутка, в противном случае получите out_of_range.

B>Ну и имплементация limit достаточно проста:


B>
B>template< typename T, size_t min, size_t max>
B>class limit : public T
B>{
B>


А почему бы не воспользоваться предикатом ?
template<typename T, T t_min, T t_max, typename TPred = std::less<T> >
class limit_t
// : public T - лучше сделать не наследование, а аггрегацию, чтобы была возможность использовать простой тип, IMHO
{
 T t;
public:
 //...
   inline T& data() { return t; }

   template< class V > inline self_t operator =   (V v) 
    { 
        if( TPed(v, t_min)
            throw std::out_of_range("new value not in the range - less than minimum");
        if( TPred(t_max, v)
            throw std::out_of_range("new value not in the range - more than maximum");
        
        data() = v;
        return *this; 
    }
};
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[3]: Навеяно auto_value<> ™ ( от Кодт )
От: Batiskaf Израиль http://www.mult.ru/
Дата: 10.10.04 11:53
Оценка:
Здравствуйте, _nn_, Вы писали:

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


B>>В данном случае номер порта может присваиваться из определенного промежутка, в противном случае получите out_of_range.

B>>Ну и имплементация limit достаточно проста:


B>>
B>>template< typename T, size_t min, size_t max>
B>>class limit : public T
B>>{
B>>


__>А почему бы не воспользоваться предикатом ?

__>
__>template<typename T, T t_min, T t_max, typename TPred = std::less<T> >
__>class limit_t
__>// : public T - лучше сделать не наследование, а аггрегацию, чтобы была возможность использовать простой тип, IMHO
__>{
__> T t;
__>public:
__> //...
__>   inline T& data() { return t; }

__>   template< class V > inline self_t operator =   (V v) 
__>    { 
__>        if( TPred(v, t_min)
__>            throw std::out_of_range("new value not in the range - less than minimum");
__>        if( TPred(t_max, v)
__>            throw std::out_of_range("new value not in the range - more than maximum");
        
__>        data() = v;
__>        return *this; 
__>    }
__>};
__>


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

limit_t<auto_value<int, 200>, 200, 100000> a;


лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[4]: Навеяно auto_value<> ™ ( от Кодт )
От: _nn_ www.nemerleweb.com
Дата: 10.10.04 19:23
Оценка:
Здравствуйте, Batiskaf, Вы писали:

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


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


B>>>В данном случае номер порта может присваиваться из определенного промежутка, в противном случае получите out_of_range.

B>>>Ну и имплементация limit достаточно проста:


B>>>
B>>>template< typename T, size_t min, size_t max>
B>>>class limit : public T
B>>>{
B>>>


__>>А почему бы не воспользоваться предикатом ?

__>>
__>>template<typename T, T t_min, T t_max, typename TPred = std::less<T> >
__>>class limit_t
__>>// : public T - лучше сделать не наследование, а аггрегацию, чтобы была возможность использовать простой тип, IMHO
__>>{
__>> T t;
__>>public:
__>> //...
__>>   inline T& data() { return t; }

__>>   template< class V > inline self_t operator =   (V v) 
__>>    { 
__>>        if( TPred(v, t_min)
__>>            throw std::out_of_range("new value not in the range - less than minimum");
__>>        if( TPred(t_max, v)
__>>            throw std::out_of_range("new value not in the range - more than maximum");
        
__>>        data() = v;
__>>        return *this; 
__>>    }
__>>};
__>>


B>для простых типов должна использоваться насадка auto_value, так что не вижу никаких препятствий для наследования. Что же касается параметризирования, то как сказано выше, атрибуты могут вкладываться один в другой, и тогда проблематично будет с этим:


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

B>
B>limit_t<auto_value<int, 200>, 200, 100000> a;
B>


B>лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.

Здесь вы говорите обратное от того что сказано вами выше
А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки

P.S.
В вашем коде есть небольшой недочет, а имено :
limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;

Что будет если не выбрать не 5000, а 4999 ?
Ничего

Так что нужна проверка для этого.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[5]: Навеяно auto_value<> ™ ( от Кодт )
От: Batiskaf Израиль http://www.mult.ru/
Дата: 10.10.04 21:19
Оценка:
Здравствуйте, _nn_, Вы писали:

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


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


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


B>>>>В данном случае номер порта может присваиваться из определенного промежутка, в противном случае получите out_of_range.

B>>>>Ну и имплементация limit достаточно проста:


B>>>>
B>>>>template< typename T, size_t min, size_t max>
B>>>>class limit : public T
B>>>>{
B>>>>


__>>>А почему бы не воспользоваться предикатом ?

__>>>
__>>>template<typename T, T t_min, T t_max, typename TPred = std::less<T> >
__>>>class limit_t
__>>>// : public T - лучше сделать не наследование, а аггрегацию, чтобы была возможность использовать простой тип, IMHO
__>>>{
__>>> T t;
__>>>public:
__>>> //...
__>>>   inline T& data() { return t; }

__>>>   template< class V > inline self_t operator =   (V v) 
__>>>    { 
__>>>        if( TPred(v, t_min)
__>>>            throw std::out_of_range("new value not in the range - less than minimum");
__>>>        if( TPred(t_max, v)
__>>>            throw std::out_of_range("new value not in the range - more than maximum");
        
__>>>        data() = v;
__>>>        return *this; 
__>>>    }
__>>>};
__>>>


B>>для простых типов должна использоваться насадка auto_value, так что не вижу никаких препятствий для наследования. Что же касается параметризирования, то как сказано выше, атрибуты могут вкладываться один в другой, и тогда проблематично будет с этим:


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

__>А вообще можно сделать два класса, с наследованием и без

B>>
B>>limit_t<auto_value<int, 200>, 200, 100000> a;
B>>


B>>лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.

__>Здесь вы говорите обратное от того что сказано вами выше
Ну имелось в виду простые интегральные типы, обернутые в auto_value, смысл от этого не меняется.

__>А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки


для этих целей я использую not_empty_string атрибут, просто не представляю ситуацию, когда нужна строка длинной не меньше 2 символов и не больше 9 к примеру...

__>P.S.

__>В вашем коде есть небольшой недочет, а имено :
__>
__>limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;
__>

__>Что будет если не выбрать не 5000, а 4999 ?
__>Ничего

__>Так что нужна проверка для этого.


Я не решился в конструкторе выбрасывать исключение, да и преследовалась цель защитить бизнес логику приложения от глупого пользователся, а не от глупого программиста, который делает явную ошибку в одной строке.
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[6]: Навеяно auto_value<> ™ ( от Кодт )
От: _nn_ www.nemerleweb.com
Дата: 10.10.04 21:42
Оценка:
Здравствуйте, Batiskaf, Вы писали:

B>>>
B>>>limit_t<auto_value<int, 200>, 200, 100000> a;
B>>>


B>>>лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.

__>>Здесь вы говорите обратное от того что сказано вами выше
B>Ну имелось в виду простые интегральные типы, обернутые в auto_value, смысл от этого не меняется.

__>>А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки


B>для этих целей я использую not_empty_string атрибут, просто не представляю ситуацию, когда нужна строка длинной не меньше 2 символов и не больше 9 к примеру...

Например для представления числа от 0 до 100, и есть задача чтобы все 3 цифры были, т.е. 001, 002...

__>>P.S.

__>>В вашем коде есть небольшой недочет, а имено :
__>>
__>>limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;
__>>

__>>Что будет если не выбрать не 5000, а 4999 ?
__>>Ничего

__>>Так что нужна проверка для этого.


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

А если будет такая ситуация то будет плохо, все же надо как-нибудь придумать защиту.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[7]: Навеяно auto_value<> ™ ( от Кодт )
От: Batiskaf Израиль http://www.mult.ru/
Дата: 11.10.04 09:16
Оценка:
Здравствуйте, _nn_, Вы писали:

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


B>>>>
B>>>>limit_t<auto_value<int, 200>, 200, 100000> a;
B>>>>


B>>>>лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.

__>>>Здесь вы говорите обратное от того что сказано вами выше
B>>Ну имелось в виду простые интегральные типы, обернутые в auto_value, смысл от этого не меняется.

__>>>А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки


B>>для этих целей я использую not_empty_string атрибут, просто не представляю ситуацию, когда нужна строка длинной не меньше 2 символов и не больше 9 к примеру...

__>Например для представления числа от 0 до 100, и есть задача чтобы все 3 цифры были, т.е. 001, 002...
Ну это вряд ли, форматирование строки для представления даты скорее бы подошло, но это уже не лимит.

__>>>P.S.

__>>>В вашем коде есть небольшой недочет, а имено :
__>>>
__>>>limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;
__>>>

__>>>Что будет если не выбрать не 5000, а 4999 ?
__>>>Ничего

__>>>Так что нужна проверка для этого.


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

__>А если будет такая ситуация то будет плохо, все же надо как-нибудь придумать защиту.

Да запросто:

в класс auto_value добавить в паблик следующую строку:


enum {def_value = i}; // где i это шаблонный параметр значения по умолчанию


в класс limit добавить следующее:


#include <boost/static_assert.hpp>

    BOOST_STATIC_ASSERT( min <= T::def_value );
    BOOST_STATIC_ASSERT( max >= T::def_value );
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[8]: Навеяно auto_value<> ™ ( от Кодт )
От: _nn_ www.nemerleweb.com
Дата: 11.10.04 12:15
Оценка:
Здравствуйте, Batiskaf, Вы писали:

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


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


B>>>>>
B>>>>>limit_t<auto_value<int, 200>, 200, 100000> a;
B>>>>>


B>>>>>лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.

__>>>>Здесь вы говорите обратное от того что сказано вами выше
B>>>Ну имелось в виду простые интегральные типы, обернутые в auto_value, смысл от этого не меняется.

__>>>>А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки


B>>>для этих целей я использую not_empty_string атрибут, просто не представляю ситуацию, когда нужна строка длинной не меньше 2 символов и не больше 9 к примеру...

__>>Например для представления числа от 0 до 100, и есть задача чтобы все 3 цифры были, т.е. 001, 002...
B>Ну это вряд ли, форматирование строки для представления даты скорее бы подошло, но это уже не лимит.
Ну можно придумать использования разные и не только со строкой, получится универсальный класс для многих вещей, а то так нужен еще один класс будет для реализации какой-нибудь дополнительной идеи.

__>>>>P.S.

__>>>>В вашем коде есть небольшой недочет, а имено :
__>>>>
__>>>>limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;
__>>>>

__>>>>Что будет если не выбрать не 5000, а 4999 ?
__>>>>Ничего

__>>>>Так что нужна проверка для этого.


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

__>>А если будет такая ситуация то будет плохо, все же надо как-нибудь придумать защиту.

B>Да запросто:


B>в класс auto_value добавить в паблик следующую строку:



B>
B>enum {def_value = i}; // где i это шаблонный параметр значения по умолчанию
B>


B>в класс limit добавить следующее:



B>
B>#include <boost/static_assert.hpp>

B>    BOOST_STATIC_ASSERT( min <= T::def_value );
B>    BOOST_STATIC_ASSERT( max >= T::def_value );
B>


А если использовать тип где enum не помогает, например float, будет проблема.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[9]: Навеяно auto_value<> ™ ( от Кодт )
От: Batiskaf Израиль http://www.mult.ru/
Дата: 11.10.04 12:48
Оценка:
Здравствуйте, _nn_, Вы писали:

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


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


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


B>>>>>>
B>>>>>>limit_t<auto_value<int, 200>, 200, 100000> a;
B>>>>>>


B>>>>>>лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.

__>>>>>Здесь вы говорите обратное от того что сказано вами выше
B>>>>Ну имелось в виду простые интегральные типы, обернутые в auto_value, смысл от этого не меняется.

__>>>>>А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки


B>>>>для этих целей я использую not_empty_string атрибут, просто не представляю ситуацию, когда нужна строка длинной не меньше 2 символов и не больше 9 к примеру...

__>>>Например для представления числа от 0 до 100, и есть задача чтобы все 3 цифры были, т.е. 001, 002...
B>>Ну это вряд ли, форматирование строки для представления даты скорее бы подошло, но это уже не лимит.
__>Ну можно придумать использования разные и не только со строкой, получится универсальный класс для многих вещей, а то так нужен еще один класс будет для реализации какой-нибудь дополнительной идеи.
Дык как я погляжу не очень получается придумать, второй день уже придумываем

__>>>>>P.S.

__>>>>>В вашем коде есть небольшой недочет, а имено :
__>>>>>
__>>>>>limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;
__>>>>>

__>>>>>Что будет если не выбрать не 5000, а 4999 ?
__>>>>>Ничего

__>>>>>Так что нужна проверка для этого.


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

__>>>А если будет такая ситуация то будет плохо, все же надо как-нибудь придумать защиту.

B>>Да запросто:


B>>в класс auto_value добавить в паблик следующую строку:



B>>
B>>enum {def_value = i}; // где i это шаблонный параметр значения по умолчанию
B>>


B>>в класс limit добавить следующее:



B>>
B>>#include <boost/static_assert.hpp>

B>>    BOOST_STATIC_ASSERT( min <= T::def_value );
B>>    BOOST_STATIC_ASSERT( max >= T::def_value );
B>>


__>А если использовать тип где enum не помогает, например float, будет проблема.


Ну ты нудник!

const static T  def_value = i;// где i это шаблонный параметр значения по умолчанию


Кстати, хорошо что вспомнил, на VC7 второй темплейт параметр с float не проходит, The C++ standard does not allow floating point non-type template parameters. К барьеру, мистер Кодт!
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[10]: Навеяно auto_value<> ™ ( от Кодт )
От: _nn_ www.nemerleweb.com
Дата: 11.10.04 13:14
Оценка:
Здравствуйте, Batiskaf, Вы писали:

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


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


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


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


B>>>>>>>
B>>>>>>>limit_t<auto_value<int, 200>, 200, 100000> a;
B>>>>>>>


B>>>>>>>лимит имеет смысл заводить для интегральных величин (какой смысл у limit_t<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.

__>>>>>>Здесь вы говорите обратное от того что сказано вами выше
B>>>>>Ну имелось в виду простые интегральные типы, обернутые в auto_value, смысл от этого не меняется.

__>>>>>>А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки


B>>>>>для этих целей я использую not_empty_string атрибут, просто не представляю ситуацию, когда нужна строка длинной не меньше 2 символов и не больше 9 к примеру...

__>>>>Например для представления числа от 0 до 100, и есть задача чтобы все 3 цифры были, т.е. 001, 002...
B>>>Ну это вряд ли, форматирование строки для представления даты скорее бы подошло, но это уже не лимит.
__>>Ну можно придумать использования разные и не только со строкой, получится универсальный класс для многих вещей, а то так нужен еще один класс будет для реализации какой-нибудь дополнительной идеи.
B>Дык как я погляжу не очень получается придумать, второй день уже придумываем
Если долго мучаться что-нибудь получится %)

__>>>>>>P.S.

__>>>>>>В вашем коде есть небольшой недочет, а имено :
__>>>>>>
__>>>>>>limit<auto_value<unsigned short, 5000 > 5000, 25000> m_PortNumber;
__>>>>>>

__>>>>>>Что будет если не выбрать не 5000, а 4999 ?
__>>>>>>Ничего

__>>>>>>Так что нужна проверка для этого.


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

__>>>>А если будет такая ситуация то будет плохо, все же надо как-нибудь придумать защиту.

B>>>Да запросто:


B>>>в класс auto_value добавить в паблик следующую строку:



B>>>
B>>>enum {def_value = i}; // где i это шаблонный параметр значения по умолчанию
B>>>


B>>>в класс limit добавить следующее:



B>>>
B>>>#include <boost/static_assert.hpp>

B>>>    BOOST_STATIC_ASSERT( min <= T::def_value );
B>>>    BOOST_STATIC_ASSERT( max >= T::def_value );
B>>>


__>>А если использовать тип где enum не помогает, например float, будет проблема.


B>Ну ты нудник!


B>
B>const static T  def_value = i;// где i это шаблонный параметр значения по умолчанию
B>

Не вижу что с T=float будет работать это

B>Кстати, хорошо что вспомнил, на VC7 второй темплейт параметр с float не проходит, The C++ standard does not allow floating point non-type template parameters. К барьеру, мистер Кодт!


Можно попробовать так : (извращение)
template<typename T, T t_value>
struct value_wrapper
{
 inline static T& data()
 {
  static T value=t_value;
  return value;
 }

 template<typename T2, T2 t_value2> 
 bool operator<(const value_wrapper<T2,t_value2>& r) const
 { return data()<r.data(); }
};

/*
Вариант №2 - Тогда не нужен вызов функции 

template<typename T, T t_value>
struct value_wrapper
{
 inline static T& data()
 { return value; }

 template<typename T2, T2 t_value2> 
 bool operator<(const value_wrapper<T2,t_value2>& r) const
 { return data()<r.data(); }
private:
 static const T value;
};

template<typename T, T t_value>
const T value_wrapper<T,t_value>::value = t_value;
*/

template<
        typename T,
        typename TMin = value_wrapper<T,T()>,
        typename TMax = value_wrapper<T,~T()>,
        typename TLess = std::less<T> >
class limit_t
{
public:
 T& data() { return static_cast<T&>(*this); }
 const T& data() const { return static_cast<const T&>(*this); }
 
 template<typename T2>
 limit_t& operator=(const limit_t<T2>& r)
 {
  if(TLess(data(),TMin::data())
   throw std::out_of_range("less than minimum");
  if(TLess(TMax::data(),data())
   throw std::out_of_range("more than maximum);
 //...
 }
};

template<
        typename T,
        T t_min,
        T t_max,
        typename TLess = std::less<T> >
class limit_t_pod : public limit_t<T,value_wrapper<T,t_min>,value_wrapper<T,t_max>,TLess>
{
//...
};


limit_t<int, value_wrapper<int,10>, value_wrapper<int,20> > limit_int_10_to_20;
limit_t_pod<int, 10, 20 > limit_pod_int_10_to_20;
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[11]: Навеяно auto_value<> ™ ( от Кодт )
От: Batiskaf Израиль http://www.mult.ru/
Дата: 11.10.04 16:08
Оценка:
Здравствуйте, _nn_, Вы писали:


__>>>>>А если будет такая ситуация то будет плохо, все же надо как-нибудь придумать защиту.


B>>>>Да запросто:


B>>>>в класс auto_value добавить в паблик следующую строку:



B>>>>
B>>>>enum {def_value = i}; // где i это шаблонный параметр значения по умолчанию
B>>>>


B>>>>в класс limit добавить следующее:



B>>>>
B>>>>#include <boost/static_assert.hpp>

B>>>>    BOOST_STATIC_ASSERT( min <= T::def_value );
B>>>>    BOOST_STATIC_ASSERT( max >= T::def_value );
B>>>>


__>>>А если использовать тип где enum не помогает, например float, будет проблема.


B>>Ну ты нудник!


B>>
B>>const static T  def_value = i;// где i это шаблонный параметр значения по умолчанию
B>>

__>Не вижу что с T=float будет работать это

B>>Кстати, хорошо что вспомнил, на VC7 второй темплейт параметр с float не проходит, The C++ standard does not allow floating point non-type template parameters. К барьеру, мистер Кодт!


__>Можно попробовать так : (извращение)

__>[c]
__>template<typename T, T t_value>
__>struct value_wrapper
__>{
__> inline static T& data()
__> {
__> static T value=t_value;
__> return value;
__> }

__> template<typename T2, T2 t_value2>

__> bool operator<(const value_wrapper<T2,t_value2>& r) const
__> { return data()<r.data(); }
__>};

Ха, проблема не только в том что статическая константа только интегрального типа может быть инициализирована в объявлении класса, вещественным числом даже запараметризировать темплейт нельзя, вот попробуй свой код:


typedef   value_wrapper< float, 10.1>  float_value_wrapper;


для float нужно свою специализацию auto_value ваять, что я и сказал Кодту.

Для меня же интересно несколько другое применение таких атрибутов, что бы в рантайме можно было собрать всю цепочку атрибутов, проитерировать, повызывать каждый по отдельности. Вот к примеру есть строковое поле, в которое вводится IID объекта, на него можно навесить один атрибут, контролирующий длину строки ( не менее 36 символов ) и валидность этого IID для текущей системы, типа как то так:


struct length_t : public T
{
...
    template< class V > inline self_t operator =   (V v) 
    { 
        if( v.length() != size )
            throw std::length_error("string is too big");
        data() = v;
        return *this; 
    }
...
};

template< typename T>
struct validate_iid_t : public T
{
...
    validate_iid_t () : T()
    {
      data()=default_iid;
    }
    template< class V > inline self_t operator =   (V v) 
    { 
        if( !IsValidIID(v) )
            throw std::invalid_iid_error("bla bla");
        data() = v;
        return *this; 
    }
...
};


И тогда поле класса:

length_t <valid_iid_t<std::string>, 36 > _ObjectID;


и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[12]: Навеяно auto_value<> ™ ( от Кодт )
От: _nn_ www.nemerleweb.com
Дата: 11.10.04 16:38
Оценка:
Здравствуйте, Batiskaf, Вы писали:

__>>Можно попробовать так : (извращение)

__>>
__>>template<typename T, T t_value>
__>>struct value_wrapper
__>>{
__>> inline static T& data()
__>> {
__>>  static T value=t_value;
__>>  return value;
__>> }

__>> template<typename T2, T2 t_value2> 
__>> bool operator<(const value_wrapper<T2,t_value2>& r) const
__>> { return data()<r.data(); }
__>>};

B>Ха, проблема не только в том что статическая константа только интегрального типа может быть инициализирована в объявлении класса, вещественным числом даже запараметризировать темплейт нельзя, вот попробуй свой код:

B>
B>typedef   value_wrapper< float, 10.1>  float_value_wrapper;
B>

Зато можно так
struct min_my_float
{
 static float data()
 {
  static const float value=10.1f;
  return value;
 }
};

struct max_my_float
{
 static float data()
 {
  static const float value=100.2f;
  return value;
 }
};

limit_t<float, min_my_float, max_my_float> x;


B>для float нужно свою специализацию auto_value ваять, что я и сказал Кодту.


B>Для меня же интересно несколько другое применение таких атрибутов, что бы в рантайме можно было собрать всю цепочку атрибутов, проитерировать, повызывать каждый по отдельности. Вот к примеру есть строковое поле, в которое вводится IID объекта, на него можно навесить один атрибут, контролирующий длину строки ( не менее 36 символов ) и валидность этого IID для текущей системы, типа как то так:



B>
B>struct length_t : public T
B>{
B>...
B>    template< class V > inline self_t operator =   (V v) 
B>    { 
B>        if( v.length() != size )
B>            throw std::length_error("string is too big");
B>        data() = v;
B>        return *this; 
B>    }
B>...
B>};

B>template< typename T>
B>struct validate_iid_t : public T
B>{
B>...
B>    validate_iid_t () : T()
B>    {
B>      data()=default_iid;
B>    }
B>    template< class V > inline self_t operator =   (V v) 
B>    { 
B>        if( !IsValidIID(v) )
B>            throw std::invalid_iid_error("bla bla");
B>        data() = v;
B>        return *this; 
B>    }
B>...
B>};

B>


B>И тогда поле класса:


B>
B>length_t <valid_iid_t<std::string>, 36 > _ObjectID;
B>


B>и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...


Что-то я не понял вашу идею.
Можно как-нибудь более подробно ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[13]: Навеяно auto_value<> ™ ( от Кодт )
От: Batiskaf Израиль http://www.mult.ru/
Дата: 11.10.04 17:15
Оценка:
Здравствуйте, _nn_, Вы писали:


B>>и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...


__>Что-то я не понял вашу идею.

__>Можно как-нибудь более подробно ?

Да это мысли в слух, вот тут http://www.rsdn.ru/Forum/Message.aspx?mid=775603
Автор: Batiskaf
Дата: 23.08.04
над одной идеей раздумываю, так вот идея в рантайме эти самые атрибуты обходить с тем что бы при автоматической генерации визуального интерфейса проинтерпретировать атрибуты во фронт сайт, тем самым схемы валидации можно указывать только один раз на уровне структуры данных, а при переносе структуры в другой базис (ведь диалог отображающий содержимое структуры Person это все тот же Person, та же модель, только выраженная другими элементами ) по возможности переносить и схему валидации. Надеюсь что выразился понятно...
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Re[14]: Навеяно auto_value<> ™ ( от Кодт )
От: _nn_ www.nemerleweb.com
Дата: 12.10.04 11:43
Оценка:
Здравствуйте, Batiskaf, Вы писали:

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



B>>>и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...


__>>Что-то я не понял вашу идею.

__>>Можно как-нибудь более подробно ?

B>Да это мысли в слух, вот тут http://www.rsdn.ru/Forum/Message.aspx?mid=775603
Автор: Batiskaf
Дата: 23.08.04
над одной идеей раздумываю, так вот идея в рантайме эти самые атрибуты обходить с тем что бы при автоматической генерации визуального интерфейса проинтерпретировать атрибуты во фронт сайт, тем самым схемы валидации можно указывать только один раз на уровне структуры данных, а при переносе структуры в другой базис (ведь диалог отображающий содержимое структуры Person это все тот же Person, та же модель, только выраженная другими элементами ) по возможности переносить и схему валидации. Надеюсь что выразился понятно...

Мы уже отошли от темы auto_value и от limit

Идею я понял, надеюсь
Вот только не представляю реализацию, и до сих пор не понял ваш код в предыдущем посте.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Навеяно auto_value<> ™ ( от Кодт )
От: Аноним  
Дата: 13.03.05 10:02
Оценка:
up
Re[15]: Навеяно auto_value<> ™ ( от Кодт )
От: Аноним  
Дата: 13.03.05 10:06
Оценка:
up
Re: SRC: auto_value<>
От: Olegator  
Дата: 13.03.05 18:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Вот, достало ловить ошибки с неинициализованными членами больших классов, вида


Давно хотел спросить: почему бы не переделать слегка этот класс:

template< class T >
class auto_value
{
  T t_;
public:
  typedef T data_t;
  typedef auto_value& self_t;

  // конструктор по умолчанию - главное достоинство этой тулзы
  inline auto_value() : t_(T()) {}

  // конструктор с 1 параметром (в том числе - конструктор копирования)
  template< class V >
  inline auto_value(V v) : t_(v) {}

  // доступ к данному
  inline const T& data() const { return t_; }
  inline T& data() { return t_; }

  // считается, что исходный тип - простой
  inline operator T  () const { return t_; }
  inline operator T& ()       { return t_; }

  // операторы присваивания
  template< class V > inline self_t operator =   (V v) { t_ =   v; return *this; }
  template< class V > inline self_t operator +=  (V v) { t_ +=  v; return *this; }
  template< class V > inline self_t operator -=  (V v) { t_ -=  v; return *this; }
  template< class V > inline self_t operator *=  (V v) { t_ *=  v; return *this; }
  template< class V > inline self_t operator /=  (V v) { t_ /=  v; return *this; }
  template< class V > inline self_t operator %=  (V v) { t_ %=  v; return *this; }
  template< class V > inline self_t operator &=  (V v) { t_ &=  v; return *this; }
  template< class V > inline self_t operator |=  (V v) { t_ |=  v; return *this; }
  template< class V > inline self_t operator ^=  (V v) { t_ ^=  v; return *this; }
  template< class V > inline self_t operator <<= (V v) { t_ <<= v; return *this; }
  template< class V > inline self_t operator >>= (V v) { t_ >>= v; return *this; }
};


Таким образом мы получим здоровую семантику нулевого объекта (а не объекта, равного нулю). Плюс поддержку не только интегральных типов.
... << RSDN@Home 1.1.4 beta 4 rev. 303>>
Re[2]: SRC: auto_value<>
От: ssm Россия  
Дата: 14.03.05 08:43
Оценка:
Здравствуйте, Olegator, Вы писали:


O>Таким образом мы получим здоровую семантику нулевого объекта (а не объекта, равного нулю). Плюс поддержку не только интегральных типов.


автор хотел избавится от ошибок с неинициализованными членами больших классов, тоесть писать просто


class BigClass
{
...
  auto_value<int, 1> m_day;
  auto_value<int, 12> m_month;
  auto_value<int, 2005> m_year;
...
};


и забить на инициализацию данных членов в конструкторах
Re[2]: SRC: auto_value<>
От: Кодт Россия  
Дата: 14.03.05 10:17
Оценка:
Здравствуйте, Olegator, Вы писали:

O>Давно хотел спросить: почему бы не переделать слегка этот класс:


<>

O>Таким образом мы получим здоровую семантику нулевого объекта (а не объекта, равного нулю). Плюс поддержку не только интегральных типов.


Класс специально был написан для того, чтобы указывать начальное значение в объявлении объекта.
Наиболее часто я им пользуюсь с булевыми переменными и различными enum-ами, реже — с целыми числами.

Для структур нет смысла делать полнофункциональный auto_value.
По-видимому, нужно вообще семейство обёрток — для интегральных, для числовых, для структур.
Перекуём баги на фичи!
Re[3]: SRC: auto_value<>
От: yxiie Украина www.enkord.com
Дата: 14.03.05 10:27
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Класс специально был написан для того, чтобы указывать начальное значение в объявлении объекта.

К>Наиболее часто я им пользуюсь с булевыми переменными и различными enum-ами, реже — с целыми числами.

что реально пользуешся? я думал такие приколы это все теоретические изыскания...
а как же тогда быть со специализациями типа:

template<class T> void function(T t) {
    ...
}


template<> void function(int t) {
    ...
}

...

auto_value<int, 1> val;

...

function(val); // вызовется не то, что нужно
... << RSDN@Home 1.1.3 stable >>
Re[4]: SRC: auto_value<>
От: Кодт Россия  
Дата: 14.03.05 11:39
Оценка:
Здравствуйте, yxiie, Вы писали:

Y>что реально пользуешся? я думал такие приколы это все теоретические изыскания...


Реально.

Y>а как же тогда быть со специализациями типа:


Если семантика специализации не отличается от семантики первичного шаблона — то будет только потеря производительности (ради чего написана специализация).

Если же нужно добиться правильной работы — пишем шлюз
template<class T> void foo(T x) { ..... }
template<> void foo(int x) { ..... }
template<> void foo(bool x) { ..... }

template<class T, T N> void foo(auto_value<T,N> x) { foo((T)x); }
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.