Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.10.18 14:13
Оценка: +1
Есть ли какое-то практическое обоснование тому, что в C++ до сих разрешено неявное усечение значений (например, int до char)? Мне сложно понять такие неявные усечения даже в ранних версиях C, но там их еще можно худо-бедно оправдать стремлением видеть программу как можно более компактной по тексту, и общепринятым в те времена подходом "в таких языках программист должен сам следить за типами". По идее, уже в первых версиях C++ это следовало изжить, но обошлись лишь введением предупреждений компилятора. Позже добавили автоматические проверки в run-time.

Все бы ничего, но при вызове перегруженных функций из шаблонов других функций это превращается в кошмар. Например, для фактической комбинации параметров (short, int) компиляторы считают подходящими и (int, int), и (short, short), и (char, char). Что мешает в такой ситуации выбрать единственно безопасный (int, int)?

Ради чего это неявное усечение продолжают тянуть? Из старого кода вроде бы уже давно должны быть вычистить требующие его конструкции, а за использование их в новом коде — расстреливать на месте. Но в C++14 на эту тему все по-прежнему (текст C++17 сходу не нашелся).
value truncation conversion
Re: Есть ли практический смысл в неявном усечении значений?
От: Lepsik Индия figvam.ca
Дата: 11.10.18 18:47
Оценка: -1
ЕМ>Ради чего это неявное усечение продолжают тянуть? Из старого кода вроде бы уже давно должны быть вычистить требующие его конструкции, а за использование их в новом коде — расстреливать на месте. Но в C++14 на эту тему все по-прежнему (текст C++17 сходу не нашелся).

Пользуйтесь __int8, __int16, __int32, __int64
Re[2]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 11.10.18 20:14
Оценка:
Здравствуйте, Lepsik, Вы писали:

L>Пользуйтесь __int8, __int16, __int32, __int64


Почему Вы решили, будто я ими не пользуюсь?
Re: Есть ли практический смысл в неявном усечении значений?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 14.10.18 03:56
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Есть ли какое-то практическое обоснование тому, что в C++ до сих разрешено неявное усечение значений (например, int до char)?


Спроси в std-proposals, как это лучше ограничить...

Вообще, там в целочисленной арифметике и без этого паршиво.

ЕМ>Все бы ничего, но при вызове перегруженных функций из шаблонов других функций это превращается в кошмар. Например, для фактической комбинации параметров (short, int) компиляторы считают подходящими и (int, int), и (short, short), и (char, char). Что мешает в такой ситуации выбрать единственно безопасный (int, int)?


Ну если на то пошло, то автоматически должен выбираться только (short, int), все остальные только по явной конверсии.
Если уж делаете строгость типизации в этом месте — то не должно быть неявных конверсий вообще.
Разве что для констант.

ЕМ>Ради чего это неявное усечение продолжают тянуть? Из старого кода вроде бы уже давно должны быть вычистить требующие его конструкции, а за использование их в новом коде — расстреливать на месте. Но в C++14 на эту тему все по-прежнему (текст C++17 сходу не нашелся).


А как поддерживать легаси?

Я вижу пока только один вариант — вводить [[атрибутами]] контексты, где действуют новые правила.
The God is real, unless declared integer.
Отредактировано 14.10.2018 3:57 netch80 . Предыдущая версия .
Re: Есть ли практический смысл в неявном усечении значений?
От: -MyXa- Россия  
Дата: 14.10.18 05:02
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>в C++ до сих разрешено неявное усечение значений


Не нравится — запрети. -Werror=conversion или -Werror=implicit-int-conversion.
Если не поможет, будем действовать током... 600 Вольт (C)
Re[2]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 14.10.18 08:54
Оценка:
Здравствуйте, netch80, Вы писали:

N>Спроси в std-proposals, как это лучше ограничить...


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

ЕМ>>для фактической комбинации параметров (short, int) компиляторы считают подходящими и (int, int), и (short, short), и (char, char). Что мешает в такой ситуации выбрать единственно безопасный (int, int)?


N>Ну если на то пошло, то автоматически должен выбираться только (short, int), все остальные только по явной конверсии.


А если его нет? Чего ради компилятору в этой ситуации упираться в формализм и отказываться компилировать, когда он может выбрать заведомо безопасное преобразование?

N>Если уж делаете строгость типизации в этом месте — то не должно быть неявных конверсий вообще.


Тогда количество явных (то есть, ручных) определений функций с тремя-четырьмя параметрами стремится к сотне. Это действительно то, чего ожидали от программиста, предлагая ему шаблоны функций и их перегрузку? Ну, или эквилибристика с метапрограммированием, но это ж чистой воды извращение.

ЕМ>>Ради чего это неявное усечение продолжают тянуть?


N>А как поддерживать легаси?


Зачем поддерживать то легаси, к которому минимум двадцать лет никто не прикасался? Еще на стыка 90-х и 2000-х следовало объявить, что в будущем неявные усекающие преобразования будут изжиты, и на приведение программ в порядок дается, скажем, десять лет. Этого хватило бы с избытком, и в итоге проблема давно была бы ликвидирована в корне, и сейчас было бы одной головной болью меньше.

Пример налицо — переходный период от 32- к 64-разрядному коду. Пока раскладка по типам не устаканилось окончательно, в ряде компиляторов были специальные предупреждения на этот счет. Нынче 64-разрядные типы в языке ничем не отличаются от 8- или 16-разрядных, так что как-то специально их отличать уже нет нужды. Все, кому было нужно, привели свои программы в порядок, а зачем тратить ресурсы на заботу о лентяях?

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

N>Я вижу пока только один вариант — вводить [[атрибутами]] контексты, где действуют новые правила.


Это само собой, когда нужно заставить компилятор выбрать более эффективный или иным образом подходящий вариант. Но он сам должен предпочитать безопасные способы безусловно опасным.
Re[2]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 14.10.18 08:56
Оценка:
Здравствуйте, -MyXa-, Вы писали:

MX>Не нравится — запрети. -Werror=conversion или -Werror=implicit-int-conversion.


Это запретит компилятору выбирать усекающие варианты из набора перегруженных/шаблонных функций? У меня в MS VC++ таких ключей нет, поэтому проверить не на чем.
Re: Есть ли практический смысл в неявном усечении значений?
От: _NN_ www.nemerleweb.com
Дата: 14.10.18 10:39
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

Скорее всего вначале сделали, чтобы было как в C, а сейчас уже изменить сломает много кода.

Поэтому и неявное приведение 0 в указатель до сих пор осталось несмотря на то, что появился nullptr.
В GCC правда есть флаг и для этого тоже zero-as-null-pointer-constant
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 14.10.18 13:12
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Скорее всего вначале сделали, чтобы было как в C


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

_NN>а сейчас уже изменить сломает много кода.


Точнее — говнокода. Стоит ли об этом печалиться? На худой конец, добавить в компиляторы ключи для явного переключения в совместимый режим. Так ведь нет даже ключей, явно переключающих в нормальный. Как в такой ситуации можно верить в адекватность разработчиков стандарта?

_NN>Поэтому и неявное приведение 0 в указатель до сих пор осталось несмотря на то, что появился nullptr.


nullptr появился не так давно. И с нулем тоже нужно что-то делать — по крайней мере, иметь для этого возможность.

_NN>В GCC правда есть флаг и для этого тоже zero-as-null-pointer-constant


А где-то еще подобный флаг есть?
Re[3]: Есть ли практический смысл в неявном усечении значений?
От: _NN_ www.nemerleweb.com
Дата: 14.10.18 13:37
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

_NN>>а сейчас уже изменить сломает много кода.


ЕМ>Точнее — говнокода. Стоит ли об этом печалиться? На худой конец, добавить в компиляторы ключи для явного переключения в совместимый режим. Так ведь нет даже ключей, явно переключающих в нормальный. Как в такой ситуации можно верить в адекватность разработчиков стандарта?

Пока в нём есть великий и ужасный iostream в адекватность верить не получается

ЕМ>А где-то еще подобный флаг есть?

Не знаю. Возможно в clang.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[4]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 14.10.18 13:46
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>Пока в нём есть великий и ужасный iostream в адекватность верить не получается


iostream нет в языке C++.
Re[5]: Есть ли практический смысл в неявном усечении значений?
От: _NN_ www.nemerleweb.com
Дата: 17.10.18 12:30
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Здравствуйте, _NN_, Вы писали:


_NN>>Пока в нём есть великий и ужасный iostream в адекватность верить не получается


ЕМ>iostream нет в языке C++.

Т.е. то, что в стандарте не является частью языка C++ ?
По этой логике std::initializer_list , std::type_info тоже не часть языка ?
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[6]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.10.18 14:21
Оценка:
Здравствуйте, _NN_, Вы писали:

ЕМ>>iostream нет в языке C++.

_NN>Т.е. то, что в стандарте не является частью языка C++ ?

Это часть исполняющей системы языка C++. Язык — это синтаксис+семантика, остальное — внешнее.

_NN>По этой логике std::initializer_list , std::type_info тоже не часть языка ?


Если в любой из реализаций оно определено непосредственно в компиляторе (то есть, доступно всегда и безусловно), то часть языка.
Re[7]: Есть ли практический смысл в неявном усечении значений?
От: B0FEE664  
Дата: 17.10.18 14:38
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

ЕМ>Если в любой из реализаций оно определено непосредственно в компиляторе (то есть, доступно всегда и безусловно), то часть языка.


Теоретически вся std библиотека может находится внутри компилятора в бинарном виде.
И каждый день — без права на ошибку...
Re[8]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 17.10.18 18:02
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Теоретически вся std библиотека может находится внутри компилятора в бинарном виде.


Теоретически не есть практически.
Re[7]: Есть ли практический смысл в неявном усечении значений?
От: N. I.  
Дата: 18.10.18 20:56
Оценка:
Евгений Музыченко:

_NN>>Т.е. то, что в стандарте не является частью языка C++ ?


ЕМ>Это часть исполняющей системы языка C++. Язык — это синтаксис+семантика, остальное — внешнее.


Это по чьей классификации?

_NN>>По этой логике std::initializer_list , std::type_info тоже не часть языка ?


ЕМ>Если в любой из реализаций оно определено непосредственно в компиляторе (то есть, доступно всегда и безусловно), то часть языка.


А если, например, исключения не поддерживаются или их можно отключить, то exception handling — это уже типа не часть языка?
Re[8]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 20.10.18 05:29
Оценка:
Здравствуйте, N. I., Вы писали:

ЕМ>>Язык — это синтаксис+семантика, остальное — внешнее.


NI>Это по чьей классификации?


По классической. Языки программирования относятся к классу формальных языков, и лексика/синтаксис/семантика определяют тип языка.

NI>А если, например, исключения не поддерживаются или их можно отключить, то exception handling — это уже типа не часть языка?


От того, что какие-то возможности языка не реализованы или отключены, их суть не меняется.

Если считать библиотеки расширения частью языка, а не исполняющей средой, то можно договориться и до того, что plain C путем добавления нужных библиотек становится объектно-ориентированным или функциональным языком.
Re[3]: Есть ли практический смысл в неявном усечении значений?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 20.10.18 06:16
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

N>>Спроси в std-proposals, как это лучше ограничить...

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

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

ЕМ>>>Ради чего это неявное усечение продолжают тянуть?

N>>А как поддерживать легаси?
ЕМ>Зачем поддерживать то легаси, к которому минимум двадцать лет никто не прикасался? Еще на стыка 90-х и 2000-х следовало объявить, что в будущем неявные усекающие преобразования будут изжиты, и на приведение программ в порядок дается, скажем, десять лет. Этого хватило бы с избытком, и в итоге проблема давно была бы ликвидирована в корне, и сейчас было бы одной головной болью меньше.

Тут согласен, и это не единственное такое место. Но почему-то стандартизаторам не интересно.

ЕМ>Пример налицо — переходный период от 32- к 64-разрядному коду. Пока раскладка по типам не устаканилось окончательно, в ряде компиляторов были специальные предупреждения на этот счет.


Ну вообще-то она и сейчас не устаканилась, в том смысле, что есть извращённые платформы, где long == int32_t

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


N>>Я вижу пока только один вариант — вводить [[атрибутами]] контексты, где действуют новые правила.


ЕМ>Это само собой, когда нужно заставить компилятор выбрать более эффективный или иным образом подходящий вариант. Но он сам должен предпочитать безопасные способы безусловно опасным.


С нынешними нормами undefined behavior везде, куда могли впихнуть — это так не получится.
The God is real, unless declared integer.
Re[4]: Есть ли практический смысл в неявном усечении значений?
От: Евгений Музыченко Франция https://software.muzychenko.net/ru
Дата: 20.10.18 06:48
Оценка:
Здравствуйте, netch80, Вы писали:

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


N>Я бы согласился, но с подобными решениями вечно возникают какие-то подводные камни.


Например? Особенно в грамотно написанном коде, а не наколенно-рубленом.

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


Для его его может быть нужно выбирать неявно? Почему не следует потребовать явного приведения к целевому типу? На худой конец — использовать опцию компилятора или прагму.

N>Но почему-то стандартизаторам не интересно.


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

N>есть извращённые платформы, где long == int32_t


Чем, по-Вашему, они извращенные? На мой взгляд, такой выбор исходит из того, что 32-разрядная сетка вполне достаточна для представления большинства "умеренно больших" значений, поэтому нет особого смысла делать long 64-разрядным, даже при наличии аппаратной поддержки. Более того, я до последнего времени никогда не вглядывался внимательно в особенности 64-разрядного кода на x64, и наивно полагал, что 64-разрядные значения для x64 "родные", а использование 32-разрядных порождает избыточный код. По этой причине несколько лет назад переделал все переменные, хранившие даже небольшие значения типа размера, в size_t.

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

ЕМ>>Но он сам должен предпочитать безопасные способы безусловно опасным.


N>С нынешними нормами undefined behavior везде, куда могли впихнуть — это так не получится.


Вот чтоб не возникало undefined behavior, криворуких программистов нужно бить по кривым рукам как можно чаще. И компилятор это сделает эффективнее любого препода или начальника.
Re[5]: Есть ли практический смысл в неявном усечении значений?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 20.10.18 08:58
Оценка:
Здравствуйте, Евгений Музыченко, Вы писали:

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

N>>Я бы согласился, но с подобными решениями вечно возникают какие-то подводные камни.
ЕМ>Например? Особенно в грамотно написанном коде, а не наколенно-рубленом.

Вопрос не в самом коде, а в том, как это надо описать в стандарте, чтобы все согласились.

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

ЕМ>Для его его может быть нужно выбирать неявно? Почему не следует потребовать явного приведения к целевому типу? На худой конец — использовать опцию компилятора или прагму.

Я как раз имею в виду, что в явном варианте конверсия может быть как минимум truncating, checked, saturating...

N>>есть извращённые платформы, где long == int32_t


ЕМ>Чем, по-Вашему, они извращенные?


Ну если у одного и того же софтостроителя в C++ long == int32_t, а в C# long == Int64, а на чуть менее чем всех платформах вокруг тоже long == int64_t, то сомнений нет, где извращение.
Особенно учитывая, что в юниксах переход на 64 бита к тому времени состоялся, все грабли пройдены, и "собственная гордость" была тупо нелепа.

EM> На мой взгляд, такой выбор исходит из того, что 32-разрядная сетка вполне достаточна для представления большинства "умеренно больших" значений, поэтому нет особого смысла делать long 64-разрядным, даже при наличии аппаратной поддержки. Более того, я до последнего времени никогда не вглядывался внимательно в особенности 64-разрядного кода на x64, и наивно полагал, что 64-разрядные значения для x64 "родные", а использование 32-разрядных порождает избыточный код. По этой причине несколько лет назад переделал все переменные, хранившие даже небольшие значения типа размера, в size_t.


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


Ну так и можно было обойтись int в таких местах.

ЕМ>>>Но он сам должен предпочитать безопасные способы безусловно опасным.

N>>С нынешними нормами undefined behavior везде, куда могли впихнуть — это так не получится.
ЕМ>Вот чтоб не возникало undefined behavior, криворуких программистов нужно бить по кривым рукам как можно чаще. И компилятор это сделает эффективнее любого препода или начальника.

Не-а. Он не бьёт, он слишком часто маскирует это.
The God is real, unless declared integer.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.