Здравствуйте, MShura, Вы писали:
К>>А если экземпляр — это член другого класса, тогда как быть? Тут не все так просто... MS>А в чем проблема?Основное условие — все экземпляры/подэкземпляры должны создаваться через new. MS>Это так сказать цена за удобство.
Тебе не кажется, что каждый int на куче создавать — это дорогая цена?
Кроме того, такая утилитка
Здравствуйте, 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_; // добавили в новой версии, в конструкторы прописать забыли.
};
Для большого класса в любом случае существует конструктор, а порой и не один. Так что формально объект этого класса будет проинициализирован (а если нет конструктора без параметров — то компилятор еще и по пальцам надает за забывчивость) при включении его членом другого класса.
А вот для скалярных типов это действительно проблема.
Я еще раз хочу подчеркнуть: изыск возник как реальная потребность при разработке и сопровождении больших проектов.
С самого начала идея очень понравилась и немного развилась, давно практикую в своей работе такие вещи, вот решил поделиться мыслями:
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, а не 0xCDCDCDCDvoid 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 ctorinline limit() : T() {}
// ctor with 1 parameter( including copy constructor)template< class V >
inline limit(V v) : T(v) {}
//access to datainline const T& data() const { return (T&)*this; }
inline T& data() { return (T&)*this; }
// means that original type is simpleoperator T () const { return data(); }
operator const T& () const { return data(); }
operator T& () { return data(); }
//assignment operatorstemplate< 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;
}
//prefixinline self_t operator ++ ()
{
T tmp = data();
++tmp;
*this = tmp;
return *this;
}
//postfixinline 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.
Здравствуйте, 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;
}
};
Здравствуйте, _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.
Здравствуйте, 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<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно.
Здесь вы говорите обратное от того что сказано вами выше
А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки
P.S.
В вашем коде есть небольшой недочет, а имено :
Здравствуйте, _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<std::string> к примеру), так что операторов "больше/меньше" вполне достаточно. __>Здесь вы говорите обратное от того что сказано вами выше
Ну имелось в виду простые интегральные типы, обернутые в auto_value, смысл от этого не меняется.
__>А вообще в любом дополнительная функциональность не помешает, кроме того смысл для limit_t<std::string> можно придумать, например для ограничения длины строки
для этих целей я использую not_empty_string атрибут, просто не представляю ситуацию, когда нужна строка длинной не меньше 2 символов и не больше 9 к примеру...
__>P.S. __>В вашем коде есть небольшой недочет, а имено : __>
__>Что будет если не выбрать не 5000, а 4999 ? __>Ничего
__>Так что нужна проверка для этого.
Я не решился в конструкторе выбрасывать исключение, да и преследовалась цель защитить бизнес логику приложения от глупого пользователся, а не от глупого программиста, который делает явную ошибку в одной строке.
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
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. __>>В вашем коде есть небольшой недочет, а имено : __>>
__>>Что будет если не выбрать не 5000, а 4999 ? __>>Ничего
__>>Так что нужна проверка для этого.
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. __>>>В вашем коде есть небольшой недочет, а имено : __>>>
__>>>Что будет если не выбрать не 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.
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. __>>>>В вашем коде есть небольшой недочет, а имено : __>>>>
__>>>>Что будет если не выбрать не 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>>>>>>лимит имеет смысл заводить для интегральных величин (какой смысл у 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. __>>>>>В вашем коде есть небольшой недочет, а имено : __>>>>>
__>>>>>Что будет если не выбрать не 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.
Здравствуйте, Batiskaf, Вы писали:
B>Здравствуйте, _nn_, Вы писали:
__>>Здравствуйте, Batiskaf, Вы писали:
B>>>Здравствуйте, _nn_, Вы писали:
__>>>>Здравствуйте, Batiskaf, Вы писали:
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. __>>>>>>В вашем коде есть небольшой недочет, а имено : __>>>>>>
__>>>>>>Что будет если не выбрать не 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>
{
//...
};
__>>>>>А если будет такая ситуация то будет плохо, все же надо как-нибудь придумать защиту.
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(); } __>};
Ха, проблема не только в том что статическая константа только интегрального типа может быть инициализирована в объявлении класса, вещественным числом даже запараметризировать темплейт нельзя, вот попробуй свой код:
для 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;
}
...
};
и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
B>Ха, проблема не только в том что статическая константа только интегрального типа может быть инициализирована в объявлении класса, вещественным числом даже запараметризировать темплейт нельзя, вот попробуй свой код:
B>
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>и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...
Что-то я не понял вашу идею.
Можно как-нибудь более подробно ?
B>>и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...
__>Что-то я не понял вашу идею. __>Можно как-нибудь более подробно ?
над одной идеей раздумываю, так вот идея в рантайме эти самые атрибуты обходить с тем что бы при автоматической генерации визуального интерфейса проинтерпретировать атрибуты во фронт сайт, тем самым схемы валидации можно указывать только один раз на уровне структуры данных, а при переносе структуры в другой базис (ведь диалог отображающий содержимое структуры Person это все тот же Person, та же модель, только выраженная другими элементами ) по возможности переносить и схему валидации. Надеюсь что выразился понятно...
Will I live tomorrow? Well I just can't say
But I know for sure — I don't live today.
Jimi Hendrix.
Здравствуйте, Batiskaf, Вы писали:
B>Здравствуйте, _nn_, Вы писали:
B>>>и хотелось бы использовать эти атрибуты в рантайме динамически, например каждый атрибут будет имплементировать несколько виртуальных функций, Next ( для навигации и перехода к следующему атрибуту ), возможность посетить атрибут, много крутых полезных вещей можно из этого поиметь...
__>>Что-то я не понял вашу идею. __>>Можно как-нибудь более подробно ?
B>Да это мысли в слух, вот тут http://www.rsdn.ru/Forum/Message.aspx?mid=775603
над одной идеей раздумываю, так вот идея в рантайме эти самые атрибуты обходить с тем что бы при автоматической генерации визуального интерфейса проинтерпретировать атрибуты во фронт сайт, тем самым схемы валидации можно указывать только один раз на уровне структуры данных, а при переносе структуры в другой базис (ведь диалог отображающий содержимое структуры Person это все тот же Person, та же модель, только выраженная другими элементами ) по возможности переносить и схему валидации. Надеюсь что выразился понятно...
Мы уже отошли от темы auto_value и от limit
Идею я понял, надеюсь
Вот только не представляю реализацию, и до сих пор не понял ваш код в предыдущем посте.