несколько вопросов по С++
От: sergey2b ЮАР  
Дата: 12.12.19 11:58
Оценка:
подскажите пожалуйста как запретить инстансирование template если тип из typename T не являеться безнаковым


есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)
Re: несколько вопросов по С++
От: Chorkov Россия  
Дата: 12.12.19 12:09
Оценка: 13 (2) +1
Здравствуйте, sergey2b, Вы писали:

S>подскажите пожалуйста как запретить инстансирование template если тип из typename T не являеться безнаковым


template<typename T>
class Foo
{
     static_assert( ! std::is_signed_v<T>  ,  "T should be unsigned!" );
     //...



S>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)


Ввести собстевенный тип, с переопределенными опереациями. Готового в стандарте нет.
Re: несколько вопросов по С++
От: rg45 СССР  
Дата: 12.12.19 13:52
Оценка: 10 (1) +1
Здравствуйте, sergey2b, Вы писали:

S>подскажите пожалуйста как запретить инстансирование template если тип из typename T не являеться безнаковым


Альтернативой static_assert-у является использование SFINAE:

#include <utility>

template <typename, typename = void>
class Foo;

template <typename T>
class Foo<T, std::enable_if_t<std::is_unsigned_v<T>>> {

};


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

Второе преимущество проявляется, когда мы имеем дело с шаблонными функциями — иногда нужно просто исключить какую-то шаблонную перегрузку или специализацию при поиске кандидатов на подстановку, а не получить ошибку компиляции.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 13.12.2019 9:01 rg45 . Предыдущая версия . Еще …
Отредактировано 12.12.2019 13:55 rg45 . Предыдущая версия .
Re: несколько вопросов по С++
От: Pzz Россия https://github.com/alexpevzner
Дата: 12.12.19 14:12
Оценка:
Здравствуйте, sergey2b, Вы писали:

S>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)


Этого способа в аппаратуре-то нету.
Re[2]: несколько вопросов по С++
От: sergey2b ЮАР  
Дата: 12.12.19 14:22
Оценка:
Здравствуйте, Pzz, Вы писали:

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


S>>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)


Pzz>Этого способа в аппаратуре-то нету.


я точно помню что использовал библиотеку из буста для этого
Re[2]: несколько вопросов по С++
От: Videoman Россия https://hts.tv/
Дата: 12.12.19 14:33
Оценка:
Здравствуйте, Pzz, Вы писали:

Pzz>Этого способа в аппаратуре-то нету.


Ну смотря какая целочисленная операция конечно. Но С(Carry) и V(oVerflow) флаги все же есть.
Re[2]: несколько вопросов по С++
От: удусекшл  
Дата: 12.12.19 14:37
Оценка:
Здравствуйте, Chorkov, Вы писали:


S>>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)


C>Ввести собстевенный тип, с переопределенными опереациями. Готового в стандарте нет.


Всегда удивляло, почему нет ничего подобного, начиная с чистой сишечки. Флаг переполнения/заёма есть имхо во всех процах, а где нет — могли бы на уровне библиотеки эмулировать
Re[3]: несколько вопросов по С++
От: Pzz Россия https://github.com/alexpevzner
Дата: 12.12.19 16:26
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Ну смотря какая целочисленная операция конечно. Но С(Carry) и V(oVerflow) флаги все же есть.


Я имею ввиду, нету исключения, как от деления на 0. Т.е., если контролировать переполнение надо, то флаги придется явно проверять. Возможно даже, что если написать эту проверку на Си, умный компилятор догадается упростить ее до условного перехода после операции. Но может и не догадаться.
Re: несколько вопросов по С++
От: PM  
Дата: 12.12.19 19:39
Оценка: 5 (1)
Здравствуйте, sergey2b, Вы писали:

S>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)


У микрософта когда-то была библиотека SafeInt, ну и в Boost конечно же тоже есть. Но, похоже, в эпоху 64 бит никого особенно это не беспокоит (или задач таких для целочисленной арифметики нет?)
Re: несколько вопросов по С++
От: Шахтер Интернет  
Дата: 12.12.19 23:27
Оценка:
Здравствуйте, sergey2b, Вы писали:

S>подскажите пожалуйста как запретить инстансирование template если тип из typename T не являеться безнаковым


Лучше всего -- через концепты. Если они недоступны -- есть обходной путь через enable_if. Но это уже устаревшая технология, переходите на С++20 и концепты.

S>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)


Ручками.


template <UIntType UInt>
struct Add
 {
  UInt result;
  bool carry;

  Add(UInt a,UInt b)
   {
    result=a+b;
    carry=(result<a);
   }
 };
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: несколько вопросов по С++
От: rg45 СССР  
Дата: 13.12.19 00:27
Оценка:
Здравствуйте, Шахтер, Вы писали:

S>>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)

Ш>Ручками.

Ш>
Ш>    result=a+b;
Ш>    carry=(result<a);
Ш>


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

Ну и второй момент. Как быть, если это не a + b, а выражение произвольной сложности?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: несколько вопросов по С++
От: σ  
Дата: 13.12.19 05:23
Оценка: 8 (1) +1
S>>>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)
Ш>>Ручками.

Ш>>
Ш>>    result=a+b;
Ш>>    carry=(result<a);
Ш>>


R>Помнинся, этот вопрос уже обсуждался несколько лет назад и тогда мне убедительно показали, со ссылками на стандарт, что такой подход порождает UB.


Тут беззнаковые типы.
Re[4]: несколько вопросов по С++
От: rg45 СССР  
Дата: 13.12.19 07:46
Оценка:
Здравствуйте, σ, Вы писали:

R>>Помнинся, этот вопрос уже обсуждался несколько лет назад и тогда мне убедительно показали, со ссылками на стандарт, что такой подход порождает UB.


σ>Тут беззнаковые типы.


Если не трудно, можешь чуть более развернуто раскрыть тему?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: несколько вопросов по С++
От: Шахтер Интернет  
Дата: 13.12.19 08:22
Оценка: 8 (1)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Шахтер, Вы писали:


S>>>есть ли в современном С++ что либо позволяюшее определить что целочисленная операция даст переполнение (или надо каждый раз самому проверять как в Си)

Ш>>Ручками.

Ш>>
Ш>>    result=a+b;
Ш>>    carry=(result<a);
Ш>>


R>Помнинся, этот вопрос уже обсуждался несколько лет назад и тогда мне убедительно показали, со ссылками на стандарт, что такой подход порождает UB.


Нет, не порождает. Это совершенно правильный код. Семантика операций беззнаковых целочисленных типов однозначно определена стандартом.

R>Ну и второй момент. Как быть, если это не a + b, а выражение произвольной сложности?


Можно обернуть UInt в структуру, и определить все операции. Признак переполнения переносить между операциями.
Но это в общем случае не нужно. Как правило, на практике достаточно элементарных вещей тип сложения и умножения.

Update.

У меня есть пример такой реализации.

тип SLen
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Отредактировано 13.12.2019 9:28 Шахтер . Предыдущая версия .
Re[4]: несколько вопросов по С++
От: rg45 СССР  
Дата: 13.12.19 08:50
Оценка:
Здравствуйте, Шахтер, Вы писали:

R>>Помнинся, этот вопрос уже обсуждался несколько лет назад и тогда мне убедительно показали, со ссылками на стандарт, что такой подход порождает UB.

Ш>Нет, не порождает. Это совершенно правильный код. Семантика операций беззнаковых целочисленных типов однозначно определена стандартом.

Возможно, я что-то неправильно понимаю, конечкно. Растолкуйте мне, пожалуйста, кто-нибудь вот этот пункт:

https://timsong-cpp.github.io/cppwp/expr#pre-4

If during the evaluation of an expression, the result is not mathematically defined or not in the range of representable values for its type, the behavior is undefined.

--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: несколько вопросов по С++
От: Шахтер Интернет  
Дата: 13.12.19 09:31
Оценка: 16 (1)
Здравствуйте, rg45, Вы писали:

R>Здравствуйте, Шахтер, Вы писали:


R>>>Помнинся, этот вопрос уже обсуждался несколько лет назад и тогда мне убедительно показали, со ссылками на стандарт, что такой подход порождает UB.

Ш>>Нет, не порождает. Это совершенно правильный код. Семантика операций беззнаковых целочисленных типов однозначно определена стандартом.

R>Возможно, я что-то неправильно понимаю, конечкно. Растолкуйте мне, пожалуйста, кто-нибудь вот этот пункт:


Поведение беззнаковых типов трактуется следующим пунктом

Unsigned integers shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value
representation of that particular size of integer.


This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting
unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the
resulting unsigned integer type.

В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[6]: несколько вопросов по С++
От: rg45 СССР  
Дата: 13.12.19 10:19
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Поведение беззнаковых типов трактуется следующим пунктом


Ш>

Ш>Unsigned integers shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value
Ш>representation of that particular size of integer.


Ш>

Ш>This implies that unsigned arithmetic does not overflow because a result that cannot be represented by the resulting
Ш>unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the
Ш>resulting unsigned integer type.


Спасибо. Сейчас формулировки меняются, но вывод остается тем же:

https://timsong-cpp.github.io/cppwp/basic.types#basic.fundamental-2

For each of the standard signed integer types, there exists a corresponding (but different) standard unsigned integer type: “unsigned char”, “unsigned short int”, “unsigned int”, “unsigned long int”, and “unsigned long long int”. Likewise, for each of the extended signed integer types, there exists a corresponding extended unsigned integer type. The standard and extended unsigned integer types are collectively called unsigned integer types. An unsigned integer type has the same width N as the corresponding signed integer type. The range of representable values for the unsigned type is 0 to 2N−1 (inclusive); arithmetic for the unsigned type is performed modulo 2N. [ Note: Unsigned arithmetic does not overflow. Overflow for signed arithmetic yields undefined behavior ([expr.pre]). — end note]

--
Не можешь достичь желаемого — пожелай достигнутого.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.