2016-11-09 7 views
3

Как мы можем сказать, компилятор C++, что следует избегать неявного приведения при использовании арифметических операторов, таких как + и /, то есть,Inhibit неявного преобразования при использовании арифметических операторов

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 
// ... 
+1

Вы пробовали -Wpedantic? – themagicalyang

+1

Добавьте -Werror в свою сборку, чтобы превратить эти предупреждения в жесткие ошибки. – StoryTeller

ответ

4

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

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

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

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

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

+0

Хорошее использование шаблонов! –

+0

@EdgarRokyan: Он есть сейчас: спасибо! – Bathsheba

+0

Почему бы не templatize сам оператор +? – themagicalyang

1

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

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

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

1

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

Другим интересным методом является использование opaque typedef. Вы можете ознакомиться с этой статьей here очень интересный разговор и его реализация.

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

Смежные вопросы