Запретить неявное преобразование при использовании арифметических операторов
Как мы можем сказать компилятору C++, что он должен избегать неявного приведения при использовании арифметических операторов, таких как +
а также /
т.е.
size_t st_1, st_2;
int i_1, i_2;
auto st = st_1 + st_2; // should compile
auto i = i_1 + i_2; // should compile
auto error_1 = st_1 + i_2; // should not compile
auto error_2 = i_1 + st_2; // should not compile
// ...
3 ответа
К сожалению, язык определяет, что должно произойти при добавлении int
к size_t
(см. его правила для продвижения типов), поэтому вы не можете вызвать ошибку времени компиляции.
Но вы могли бы построить свой собственный add
функция, чтобы аргументы были одного типа:
template <class Y>
Y add(const Y& arg1, const Y& arg2)
{
return arg1 + arg2;
}
Ссылки на константы предотвращают любое преобразование типов, а шаблон заставляет оба аргумента быть одного типа.
Это всегда будет работать в вашем конкретном случае, так как size_t
должен быть unsigned
тип:
Со встроенными (не классовыми) типами невозможно предотвратить нежелательные неявные преобразования типов.
Некоторые компиляторы могут быть настроены на выдачу предупреждений для операций, включающих подозрительные преобразования, но это не охватывает все возможные неявные преобразования (в конце концов, преобразование из short
в long
сохраняет значение, поэтому не все компиляторы сообщат об этом как о подозрительном). И некоторые из этих компиляций также могут быть настроены на выдачу ошибок, когда они выдают предупреждения.
С типами классов C++ можно предотвращать неявные преобразования, создавая конструкторы explicit
и не определяя операторы преобразования (например, функцию-член класса с именем operator int()
).
Для типа класса также возможно предоставить числовые операторы (operator+()
и т. д.), которые принимают только операнды требуемых типов. Проблема в том, что это не обязательно мешает продвижению встроенных типов, участвующих в таких выражениях. Например, класс, который обеспечивает operator+(int) const
(так some_object = some_other_object + some_int
будет работать) не остановит выражение как some_other_object + some_short
от компиляции (как some_short
может быть косвенно повышен до int
).
Что в основном означает, что можно предотвратить неявные преобразования в типы классов, но не предотвратить продвижение в выражениях с числовыми операторами.
Лучший ответ, который я могу вам дать, это использовать юниты: взгляните на буст.
Еще одним интересным методом является использование opaque typedef
Вы можете взглянуть на эту статью Toward Opaque Typedef, здесь очень интересная беседа и реализация.
Надеюсь, что материал может быть полезным