Запретить неявное преобразование при использовании арифметических операторов

Как мы можем сказать компилятору 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, здесь очень интересная беседа и реализация.

Надеюсь, что материал может быть полезным

Другие вопросы по тегам