Ответ 1
Унифицированная инициализация предотвращает сужение.
Это следует за (не работает, по запросу):
struct Foo {
explicit Foo(unsigned int x) : x(x) {}
unsigned int x;
};
int main() {
Foo f = Foo{-1};
std::cout << f.x << std::endl;
}
По возможности используйте обычную инициализацию (Foo{-1}
вместо Foo(-1)
).
ИЗМЕНИТЬ
В качестве альтернативы, как запрошено OP в комментариях, решение, которое работает также с С++ 98, заключается в объявлении private
конструкторов, получающих int
(long int
и т.д.).
Нет необходимости определять их.
Пожалуйста, обратите внимание, что = delete
также будет хорошим решением, как это предлагается в другом ответе, но это тоже происходит с С++ 11.
РЕДАКТИРОВАТЬ 2
Я хотел бы добавить еще одно решение, событие, хотя оно действительно с С++ 11.
Идея основана на предположении Voo (см. Комментарии ответа Брайана для дальнейших подробностей) и использует SFINAE для аргументов конструктора.
Это следует за минимальным рабочим примером:
#include<type_traits>
struct S {
template<class T, typename = typename std::enable_if<std::is_unsigned<T>::value>::type>
S(T t) { }
};
int main() {
S s1{42u};
// S s2{42}; // this doesn't work
// S s3{-1}; // this doesn't work
}