tipos datos conversion c++ implicit-conversion unsigned-integer

conversion de tipos de datos en c++



¿Cómo evitar la conversión implícita de int a unsigned int? (3)

Supongamos que tienes esto:

struct Foo { Foo(unsigned int x) : x(x) {} unsigned int x; }; int main() { Foo f = Foo(-1); // how to get a compiler error here? std::cout << f.x << std::endl; }

¿Es posible evitar la conversión implícita?

La única forma en que podría pensar es en proporcionar de manera explícita un constructor que tome un int y genere algún tipo de error en tiempo de ejecución si el int es negativo, pero sería mejor si pudiera obtener un error de compilación para esto.

Estoy casi seguro de que hay un duplicado, pero lo más cercano que pude encontrar es esta pregunta que más bien pregunta por qué se permite la conversión implícita.

Me interesan las soluciones C ++ 11 y pre C ++ 11, preferiblemente una que funcione en ambas.


La inicialización uniforme evita el estrechamiento.

Sigue un ejemplo (no funciona, como se solicita):

struct Foo { explicit Foo(unsigned int x) : x(x) {} unsigned int x; }; int main() { Foo f = Foo{-1}; std::cout << f.x << std::endl; }

Simplemente acostúmbrate a utilizar la inicialización uniforme ( Foo{-1} lugar de Foo(-1) ) siempre que sea posible.

EDITAR

Como alternativa, tal como lo solicitó el OP en los comentarios, una solución que también funciona con C ++ 98 es declarar como private los constructores que obtienen un int ( long int , etc.).
No hace falta definirlos realmente.
Tenga en cuenta que = delete también sería una buena solución, como se sugiere en otra respuesta, pero esa también lo es desde C ++ 11.

EDIT 2

Me gustaría agregar una solución más, aunque el evento es válido desde C ++ 11.
La idea se basa en la sugerencia de Voo (consulte los comentarios de la respuesta de Brian para obtener más detalles) y utiliza SFINAE en los argumentos del constructor.
Sigue un mínimo, ejemplo de trabajo:

#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 }


Puede forzar un error de compilación eliminando la sobrecarga no deseada.

Foo(int x) = delete;


Si desea que se le -Wsign-conversion cada vez que se produzca dicho código, y está utilizando GCC, use la opción -Wsign-conversion .

foo.cc: In function ‘int main()’: foo.cc:8:19: warning: negative integer implicitly converted to unsigned type [-Wsign-conversion] Foo f = Foo(-1); // how to get a compiler error here? ^

Si quiere un error, use -Werror=sign-conversion .