Приведение константного числа к нужному типу в точке использ
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 08.10.19 07:08
Оценка: 7 (2)
Visual Studio (2013-2019).

Сражаюсь с предупреждениями 4-го уровня.

Пример
int main()
{
    char chs[10];

    std::fill(std::begin(chs),std::end(chs),0);

    std::cout << "Hello World!\n";

    return 0;
}

Компилятор выдает предупреждение для нуля, передаваемого в std::fill:
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:  '=': conversion from 'const _Ty' to '_Ty', possible loss of data
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:         with
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:         [
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:             _Ty=int
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:         ]
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:         and
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:         [
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:             _Ty=char
1>C:\VS-BLA-BLA\include\xutility(2253,24): warning C4244:         ]
1>D:\MY-BLA-BLA\ConsoleApplication1\ConsoleApplication1.cpp(10): message :  see reference to function template instantiation 'void std::fill<_Ty*,int>(const _FwdIt,const _FwdIt,const int &)' being compiled
1>D:\MY-BLA-BLA\ConsoleApplication1\ConsoleApplication1.cpp(10): message :         with
1>D:\MY-BLA-BLA\ConsoleApplication1\ConsoleApplication1.cpp(10): message :         [
1>D:\MY-BLA-BLA\ConsoleApplication1\ConsoleApplication1.cpp(10): message :             _Ty=char,
1>D:\MY-BLA-BLA\ConsoleApplication1\ConsoleApplication1.cpp(10): message :             _FwdIt=char *
1>D:\MY-BLA-BLA\ConsoleApplication1\ConsoleApplication1.cpp(10): message :         ]

Я не хочу заморачиваться с приведением нуля к нужному типу (char, в данном случае).

  Поэтому, для устранения предупреждения, применяю такую штуку:
namespace structure{

template<int initializeValue>
class t_numeric_initializator
{
 public:
  t_numeric_initializator()
  {
  }

  operator char             () const        {return static_cast<char>            (initializeValue);}
  operator wchar_t          () const        {return static_cast<wchar_t>         (initializeValue);}

  operator unsigned char    () const        {return static_cast<unsigned char>   (initializeValue);}
  operator unsigned short   () const        {return static_cast<unsigned short>  (initializeValue);}
  operator unsigned int     () const        {return static_cast<unsigned int>    (initializeValue);}
  operator unsigned __int64 () const        {return static_cast<unsigned __int64>(initializeValue);}

  operator signed char      () const        {return static_cast<signed char>     (initializeValue);}
  operator signed short     () const        {return static_cast<signed short>    (initializeValue);}
  operator signed int       () const        {return static_cast<signed int>      (initializeValue);}
  operator signed __int64   () const        {return static_cast<signed __int64>  (initializeValue);}

  operator signed long      () const        {return static_cast<signed long>   (initializeValue);}
  operator unsigned long    () const        {return static_cast<unsigned long> (initializeValue);}

  operator float            () const        {return static_cast<float>  (initializeValue);}
  operator double           () const        {return static_cast<double> (initializeValue);}
};//class t_numeric_initializator

static t_numeric_initializator<0> zero;

}//namespace structure;

Используется так:
int main()
{
    char chs[10];

    std::fill(std::begin(chs),std::end(chs),structure::zero);

    std::cout << "Hello World!\n";

    return 0;
}

Все, предупреждений нет.

Вопрос — это нормальный велосипед? Или есть решения получше?

---
PS. У меня есть еще "t_numeric_initializator<-1> negative_one" для схожих проблем с -1.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 08.10.2019 7:26 DDDX . Предыдущая версия .
Re: Приведение константного числа к нужному типу в точке использования
От: Nuzhny Россия https://github.com/Nuzhny007
Дата: 08.10.19 07:23
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Visual Studio (2013-1019).

КД>Сражаюсь с предупреждениями 4-го уровня.

Как решить проблему не знаю, но тоже достаёт. Особенно константы float/double, которые отлично влезают в оба типа, но в коде надо вычирать один из.
Подпишусь на ответы.
Re: Приведение константного числа к нужному типу в точке исп
От: qaz77  
Дата: 08.10.19 08:19
Оценка:
Каст не нужен.
Хочет компилятор char — так дай его:
char chs[10];
std::fill(std::begin(chs),std::end(chs),'\0');
Отредактировано 08.10.2019 8:19 qaz77 . Предыдущая версия .
Re[2]: Приведение константного числа к нужному типу в точке исп
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 08.10.19 08:30
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>Каст не нужен.

Q>Хочет компилятор char — так дай его:
Q>
Q>char chs[10];
Q>std::fill(std::begin(chs),std::end(chs),'\0');
Q>


Был приведен очень упрощенный пример, базовый смысл которого — присвоить данным нулевое значение.

При этом тип самих данных не волнует.

Бывает так, что этот тип в явном виде не доступен.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Приведение константного числа к нужному типу в точке использ
От: Igore Россия  
Дата: 08.10.19 08:47
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Visual Studio (2013-2019).


КД>Вопрос — это нормальный велосипед? Или есть решения получше?

Что-то ничего кроме _STL_WARNING_LEVEL=3 в Preprocesor Definitions не придумывается, лучше это или хуже даже не знаю.
Re: Приведение константного числа к нужному типу в точке использ
От: AleksandrN Россия  
Дата: 08.10.19 08:56
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Visual Studio (2013-2019).


КД>Сражаюсь с предупреждениями 4-го уровня.


КД>Пример

КД>[ccode]
КД>int main()
КД>{
КД> char chs[10];

КД> std::fill(std::begin(chs),std::end(chs),0);


КД> std::cout << "Hello World!\n";


КД> return 0;

КД>}

КД>Вопрос — это нормальный велосипед? Или есть решения получше?



Конкретно для этого случая — char chs[10] = { 0 };
Re: Приведение константного числа к нужному типу в точке исп
От: night beast СССР  
Дата: 08.10.19 08:57
Оценка: 10 (1) +1
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вопрос — это нормальный велосипед? Или есть решения получше?


нормальный велосипед. можно сделать операторы constexpr

и сам зеро таким же.
Отредактировано 08.10.2019 9:02 night beast . Предыдущая версия .
Re[2]: Приведение константного числа к нужному типу в точке использ
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 08.10.19 08:58
Оценка:
Здравствуйте, Igore, Вы писали:

I>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>Visual Studio (2013-2019).


КД>>Вопрос — это нормальный велосипед? Или есть решения получше?

I>Что-то ничего кроме _STL_WARNING_LEVEL=3 в Preprocesor Definitions не придумывается, лучше это или хуже даже не знаю.

Такая проблема может быть где угодно. Не только в STL.

---
Наверное эта штука (t_numeric_initializator) схожа с std::nullptr_t.

Но я эту мысль глубоко не обдумывал
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Приведение константного числа к нужному типу в точке использ
От: B0FEE664  
Дата: 08.10.19 09:41
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Вопрос — это нормальный велосипед?


Мне нравится. Наверное ваш подход чем-то лучше, чем мой изложенный ниже.

КД>Или есть решения получше?


Я поступал несколько иначе: перегружал для ZeroType операторы сравнения для своего набора классов. А у классов добавлял конструторы с аргументом типа ZeroType. Впрочем, это несколько иная задача.

Пишу по памяти:
namespace xxxx
{

struct ZeroType 
{
};

ZeroType zero;

template<class T>
class A
{
  public:
    A(ZeroType);
};

bool operator == (A a, ZeroType);
bool operator == (ZeroType, A a);
....

}// namespace xxxx
И каждый день — без права на ошибку...
Re[2]: Приведение константного числа к нужному типу в точке использ
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 08.10.19 09:55
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

КД>>Вопрос — это нормальный велосипед?


BFE>Мне нравится. Наверное ваш подход чем-то лучше, чем мой изложенный ниже.


КД>>Или есть решения получше?


BFE>Я поступал несколько иначе: перегружал для ZeroType операторы сравнения для своего набора классов. А у классов добавлял конструторы с аргументом типа ZeroType. Впрочем, это несколько иная задача.


  У меня есть схожая штука:
template<typename TNumeric,size_t page_index_size>
struct t_ss_page_index
{
 private:
  typedef t_ss_page_index<TNumeric,page_index_size>   self_type;

 public:
  typedef self_type                                   page_index_type;
  typedef size_t                                      size_type;
  typedef t_ss_byte                                   byte_type;
  typedef TNumeric                                    numeric_type;

  typedef t_ss_page_index_comparer<numeric_type,
                                   page_index_size>   comparer_type;

  typedef t_ss_page_index_hash_maker<numeric_type,
                                     page_index_size> hash_maker_type;

  enum
  {
   c_size=page_index_size
  };

 private:
  ///Index data
  numeric_type data[page_index_size];

 public:
  ///Invalid page index
  static const self_type npos;

 public:
  t_ss_page_index();

  t_ss_page_index(t_zero);

  t_ss_page_index(t_negative_one);

  self_type& operator = (t_zero);

  self_type& operator = (t_negative_one);
  //....

Где
typedef t_numeric_initializator<0> t_zero;

typedef t_numeric_initializator<-1> t_negative_one;


-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re: Приведение константного числа к нужному типу в точке использ
От: Кодт Россия  
Дата: 08.10.19 10:33
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Поэтому, для устранения предупреждения, применяю такую штуку:

КД>
КД>namespace structure{

КД>template<int initializeValue>
КД>class t_numeric_initializator
КД>{
КД> public:
КД>  t_numeric_initializator()
КД>  {
КД>  }

КД>  operator char             () const        {return static_cast<char>            (initializeValue);}
КД>  operator wchar_t          () const        {return static_cast<wchar_t>         (initializeValue);}

КД>  operator unsigned char    () const        {return static_cast<unsigned char>   (initializeValue);}
КД>  operator unsigned short   () const        {return static_cast<unsigned short>  (initializeValue);}
КД>  operator unsigned int     () const        {return static_cast<unsigned int>    (initializeValue);}
КД>  operator unsigned __int64 () const        {return static_cast<unsigned __int64>(initializeValue);}

КД>  operator signed char      () const        {return static_cast<signed char>     (initializeValue);}
КД>  operator signed short     () const        {return static_cast<signed short>    (initializeValue);}
КД>  operator signed int       () const        {return static_cast<signed int>      (initializeValue);}
КД>  operator signed __int64   () const        {return static_cast<signed __int64>  (initializeValue);}

КД>  operator signed long      () const        {return static_cast<signed long>   (initializeValue);}
КД>  operator unsigned long    () const        {return static_cast<unsigned long> (initializeValue);}

КД>  operator float            () const        {return static_cast<float>  (initializeValue);}
КД>  operator double           () const        {return static_cast<double> (initializeValue);}
КД>};//class t_numeric_initializator

КД>static t_numeric_initializator<0> zero;

КД>}//namespace structure;
КД>


Зачем туча операторов? Почему бы не шаблонный
template<class T> operator T() const { return static_cast<T>(initializeValue); }
Перекуём баги на фичи!
Re[2]: Приведение константного числа к нужному типу в точке использ
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 08.10.19 10:37
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Зачем туча операторов? Почему бы не шаблонный

К>
К>template<class T> operator T() const { return static_cast<T>(initializeValue); }
К>

Да перестраховки — хотелось явно определить каждый вариант использования этого класса
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Приведение константного числа к нужному типу в точке исп
От: qaz77  
Дата: 08.10.19 14:59
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Был приведен очень упрощенный пример, базовый смысл которого — присвоить данным нулевое значение.


КД>При этом тип самих данных не волнует.


КД>Бывает так, что этот тип в явном виде не доступен.


А, понятно.

У решения с шаблоном есть принципиальное ограничение, что инициализаторы могут быть только целочисленные.
Так не получится:
t_numeric_initializator<3.14> pi_initializer;

Хотя касты к вещественным типам в шаблоне есть.

В принципе, хватило бы преобразования к самому маленькому целочисленному типу int8_t и uint8_t.
Тогда неявный каст от меньшего к большему будет без "possible loss of data".
Re[3]: Приведение константного числа к нужному типу в точке использ
От: _niko_ Россия  
Дата: 08.10.19 15:23
Оценка: 6 (2)
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Да перестраховки — хотелось явно определить каждый вариант использования этого класса



template<int initializeValue>
class t_numeric_initializator
{
private:

    template<class... Types>
    struct is_support_impl {};

    template<class Type>
    struct is_support_impl<Type> : std::false_type {};

    template<class Type, class FirstType, class... OtherTypes>
    struct is_support_impl<Type, FirstType, OtherTypes...>
        : std::conditional_t<std::is_same_v<Type, FirstType>, std::true_type, is_support_impl<Type, OtherTypes...>>
    {};

    template< class Type >
    struct is_support : is_support_impl<Type,
        char, signed char, unsigned char, wchar_t,
        signed short, unsigned short,
        signed int, unsigned int,
        signed long, unsigned long,
        signed __int64, unsigned __int64,
        float, double
    >
    {};

public:

    t_numeric_initializator() {}

    template <class Type>
    inline constexpr operator Type() const noexcept
    {
        static_assert(is_support<Type>::value);
        return static_cast<Type>(initializeValue);
    }
};
Re[4]: Приведение константного числа к нужному типу в точке использ
От: rg45 СССР  
Дата: 08.10.19 18:36
Оценка: 8 (1)
Здравствуйте, _niko_, Вы писали:

__>Здравствуйте, Коваленко Дмитрий, Вы писали:


КД>>Да перестраховки — хотелось явно определить каждый вариант использования этого класса


  is_support
__>
__>template<int initializeValue>
__>class t_numeric_initializator
__>{
__>private:

__>    template<class... Types>
__>    struct is_support_impl {};

__>    template<class Type>
__>    struct is_support_impl<Type> : std::false_type {};

__>    template<class Type, class FirstType, class... OtherTypes>
__>    struct is_support_impl<Type, FirstType, OtherTypes...>
__>        : std::conditional_t<std::is_same_v<Type, FirstType>, std::true_type, is_support_impl<Type, OtherTypes...>>
__>    {};

__>    template< class Type >
__>    struct is_support : is_support_impl<Type,
__>        char, signed char, unsigned char, wchar_t,
__>        signed short, unsigned short,
__>        signed int, unsigned int,
__>        signed long, unsigned long,
__>        signed __int64, unsigned __int64,
__>        float, double
    >>
__>    {};

__>public:

__>    t_numeric_initializator() {}

__>    template <class Type>
__>    inline constexpr operator Type() const noexcept
__>    {
__>        static_assert(is_support<Type>::value);
__>        return static_cast<Type>(initializeValue);
__>    }
__>};


Так может, еще проще?

template <typename T>
using is_support = std::bool_constant<std::is_integral_v<T> || std::is_floating_point_v<T>>;
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Приведение константного числа к нужному типу в точке использ
От: qaz77  
Дата: 09.10.19 07:37
Оценка:
Здравствуйте, rg45, Вы писали:

R>Так может, еще проще?


R>
R>template <typename T>
R>using is_support = std::bool_constant<std::is_integral_v<T> || std::is_floating_point_v<T>>;
R>


Только is_integral еще bool добавляет.
Re[6]: Приведение константного числа к нужному типу в точке использ
От: rg45 СССР  
Дата: 09.10.19 08:28
Оценка:
Здравствуйте, qaz77, Вы писали:

Q>Только is_integral еще bool добавляет.


Ну так bool и допускает инициализацию нулем. Исключить-то не проблема, только стоит ли это делать.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[7]: Приведение константного числа к нужному типу в точке использ
От: qaz77  
Дата: 09.10.19 10:17
Оценка:
Здравствуйте, rg45, Вы писали:

R>Ну так bool и допускает инициализацию нулем. Исключить-то не проблема, только стоит ли это делать.


Нужно или нет, надо у ТС спрашивать.

Просто слово numeric намекает именно на числа и там не обязательно ноль, а t_numeric_initailizer<42> может быть.
В этом контексте странно, что есть касты в char и wchar_t, но это еще можно понять.
Также странно, что вещественные числа можно только целочисленными константами инициализировать.

Не выполняется принцип наименьшего удивления, на мой взгляд.
Re[8]: Приведение константного числа к нужному типу в точке
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 09.10.19 10:43
Оценка:
Здравствуйте, qaz77, Вы писали:

R>>Ну так bool и допускает инициализацию нулем. Исключить-то не проблема, только стоит ли это делать.


Q>Нужно или нет, надо у ТС спрашивать.


Q>Просто слово numeric намекает именно на числа и там не обязательно ноль, а t_numeric_initailizer<42> может быть.

Q>В этом контексте странно, что есть касты в char и wchar_t, но это еще можно понять.
Q>Также странно, что вещественные числа можно только целочисленными константами инициализировать.

Q>Не выполняется принцип наименьшего удивления, на мой взгляд.


Изначально эта штука использовалась для -1. Нужно было нечто для безболезненной установки значений 0xFFFF....

Поддержки для float/double/char/wchar_t тогда не было. Это было в 2008 году.

Значительно позже прикрутил поддержку для нуля.

Посмотрел, подумал и добавил преобразования для float, double, char, wchar_t.

bool не нужен
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Отредактировано 09.10.2019 10:51 DDDX . Предыдущая версия .
Re[9]: Приведение константного числа к нужному типу в точке
От: qaz77  
Дата: 09.10.19 11:31
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>Значительно позже прикрутил поддержку для нуля.


Вот это имеется в виду под "поддержкой для нуля"?
static t_numeric_initializator<0> zero;


Почему не const или даже constexpr?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.