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

Как мы можем сообщить компилятору 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
// ...

person abraham_hilbert    schedule 09.11.2016    source источник
comment
Вы пробовали -Wpedantic?   -  person themagicalyang    schedule 09.11.2016
comment
Добавьте -Werror в свою сборку, чтобы превратить эти предупреждения в серьезные ошибки.   -  person StoryTeller - Unslander Monica    schedule 09.11.2016


Ответы (3)


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

Но вы можете создать свою собственную функцию add, чтобы аргументы были одного типа:

template <class Y>
Y add(const Y& arg1, const Y& arg2)
{
    return arg1 + arg2;
}

Ссылки на константы предотвращают любое преобразование типов, а шаблон заставляет оба аргумента иметь один и тот же тип.

Это будет всегда работать в вашем конкретном случае, поскольку size_t должен быть типом unsigned:

person Bathsheba    schedule 09.11.2016
comment
Хорошее использование шаблонов! - person Edgar Rokjān; 09.11.2016
comment
Почему бы не создать шаблон самого оператора+? - person themagicalyang; 09.11.2016
comment
Хороший вопрос. Но вам не разрешено вводить глобальные операторы для встроенных типов. - person Bathsheba; 09.11.2016
comment
Указание его как constexpr не помешает - person StoryTeller - Unslander Monica; 09.11.2016

Лучший ответ, который я могу вам дать, это использовать единицы: взгляните на усилитель.

Еще одним интересным методом является использование opaque typedef, вы можете ознакомиться с этой статьей К непрозрачному Typedef здесь очень интересный разговор и реализация.

Надеюсь материал будет полезен

person Elvis Dukaj    schedule 09.11.2016

Со встроенными (не классовыми) типами невозможно предотвратить нежелательные неявные преобразования типов.

Некоторые компиляторы могут быть настроены на выдачу предупреждений об операциях, связанных с подозрительными преобразованиями, но это не распространяется на все возможные неявные преобразования (в конце концов, преобразование из 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).

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

person Peter    schedule 09.11.2016