2010-04-28 8 views
10

¿Hay alguna manera de hacer que el tipo enum sea sin firmar? El siguiente código me da una advertencia sobre la comparación firmada/no firmada.¿Hay alguna manera de hacer que el tipo `enum` no esté firmado?

enum EEE { 
    X1 = 1 
}; 

int main() 
{ 
    size_t x = 2; 
    EEE t = X1; 
    if (t < x) std::cout << "ok" << std::endl; 

    return 0; 
} 

He tratado de forzar compilador que utilice el tipo subyacente sin signo de enumeración con lo siguiente:

enum EEE { 
    X1 = 1, 
    XN = 18446744073709551615LL 
    // I've tried XN = UINT_MAX (in Visual Studio). Same warning. 
}; 

Pero eso sigue dando la advertencia.


Cambio constante a UINT_MAX hace trabajar en GNU C++ que habían de ser de acuerdo con la norma. Parece ser un error en VS. Gracias a James por la indirecta.

+0

relacionada, pero no duplicar: http://stackoverflow.com/questions/2579230/signedness-of-enum-in-c-c99-c-cx-gnu-c -gnu-c99 –

+0

http://stackoverflow.com/questions/159034/ – sbi

+2

@sbi, eso no es un duplicado, porque C++ Standard da una pista sobre cómo cambiar el tipo undelying a unsigned int. Y estoy tratando de usar eso. –

Respuesta

8

Usted puede tratar de:

enum EEE { 
    X1 = 1, 
    XN = -1ULL 
}; 

Sin la U, se firmó el literal entero.

(Por supuesto, esto supone que su aplicación es compatible con long long; supongo que lo hace ya que la pregunta original utiliza LL, de lo contrario, se puede utilizar para una ULlong).

+0

Esto funciona en GNU C++, pero no en Visual Studio. Parece ser un error en VS. Este código también es correcto, pero es mejor usar 'UINT_MAX'. –

+0

@James, Ah, de hecho. Si lo haces con "LLU" en lugar de solo con "U" como hice, ya no puede elegir "largo". ¡Una buena forma de evitar las palabras poco claras de lo que significa "más grande"! Volvería a votar si usa un macro de límite o '-1ULL' (o' -1UL' en C++ 03 o implementación larga) :) –

+0

'ULLONG_MAX' tampoco funciona en VC++. Creo que el compilador cree que puede generar código de 128 bits. –

2

No en la versión actual de C++. C++ 0x proporcionará enumeraciones fuertemente tipadas.

Por el momento, puede usar if (static_cast<size_t>(t) < x) para eliminar la advertencia.

+2

Estoy tratando de evitar más 'static_cast''s. –

0

Por qué no

enum EEE { 
    X1 = 1, 
    x = 2 // pick more descriptive name, a'course 
}; 

o

if (size_t(t) < x) 
+2

¿Cómo sabe que sus valores enum para el enum EEE no están firmados? Se parecen a mí. – chollida

+0

@chollida, el objetivo final era deshacerse de la advertencia, no anularla, sospecho. Su manera logra eso. –

+0

@cohollida: la pregunta es cómo hacer que el tipo enum no sea firmado. Eso implicaría que no pondrá valores negativos, o si quiere modulo aritmético si lo hace. – Potatoswatter

2

Usted también podría sobrecargar los operadores si quieres compararlo

enum EEE { 
    X1 = 1 
}; 

bool operator<(EEE e, std::size_t u) { 
    return (int)e < (int)u; 
} 

Sin embargo, usted tiene que hacer que la danza para cualquier entero escribe en el lado derecho. De lo contrario, si lo haces e < 2 sería ambiguo: el compilador podría usar tu operator< haciendo coincidir el lado izquierdo exactamente pero necesitando una conversión en el lado derecho, o su operador incorporado, necesitando una promoción para el lado izquierdo y coincidiendo exactamente con el lado derecho .

Así que, finalmente, me gustaría poner las siguientes versiones:

/* everything "shorter" than "int" uses either int or unsigned */ 
bool operator<(EEE e, int u) { 
    return (int)e < (int)u; 
} 

bool operator<(EEE e, unsigned u) { 
    return (unsigned int)e < (unsigned int)u; 
} 


bool operator<(EEE e, long u) { 
    return (long)e < (long)u; 
} 

bool operator<(EEE e, unsigned long u) { 
    return (unsigned long)e < (unsigned long)u; 
} 

/* long long if your compiler has it, too */ 

No es muy agradable :) Pero, al menos, el usuario de su enumeración fácil se va. Sin embargo, si en última instancia no desea comparar con el int ordinario, pero en contra de algún valor significativo, haría lo que otro tipo sugirió, y agregue otro enumerador que tenga como valor 2 y asígnele un nombre. De esa forma, las advertencias desaparecerán también.

+0

bastante detallado, pero hace el trabajo si está buscando evitar static_cast –

+0

'-1U'? ¿Estás tratando de aplicar un operador menos unario al tipo sin firmar? ¿Debería eso cambiar el tipo de firmado? –

+0

@Kirill, se mantendrá 'unsigned' pero cambiará su valor a' UINT_MAX'. Entonces no necesitas el encabezado de límites. –

1

por C++ Enumeration Declarations on MSDN:

enum EEE : unsigned { 
    X1 = 1 
}; 
+0

no compila –

+0

@ KirillV.Lyadvinsky: ¿en serio? Debería. MSVC dice que compila esto desde MSVC2005. –

+1

He buscado *** sin firmar *** en la referencia, pero no aparece como usted proporcionó anteriormente. *** sin firmar *** solo se usa una vez en una oración. ¿Estás seguro de que la referencia es correcta? – jww

Cuestiones relacionadas