2010-09-28 15 views
11

Tengo un problema que es bastante común en el código que estoy escribiendo en el momento en que quiero tener un número entero que solo puede existir dentro de un cierto rango donde el rango es [inicio, fin]. Básicamente, quiero poder hacer algo como lo siguiente:¿Hay una clase de entero cíclico estándar en C++?

cyclic_int ci(4, 8); 

ci = 4; 
assert(ci == 4); 
ci += 3; 
assert(ci == 7); 
ci += 2; 
assert(ci == 5); 
assert(ci == 13); 

Y eso debería ser cierto. Básicamente, la clase aplica automáticamente el módulo (%) y el entero actúa como un entero cíclico en el rango con el que lo inicio. Podría implementar esta clase yo mismo y sobrecargar a todos los operadores comunes para que funcione bien con enteros normales, pero parece una clase útil que alguien pudo haber hecho antes.

Así que mi pregunta es esta, ¿existe una clase común como esta en algún lugar que todos usan o estoy pensando en hacerlo de la manera incorrecta y hay una manera mejor y más simple. (Mi objetivo es no tener que pensar constantemente en aplicar el operador% o cualquier función similar sobre él) Gracias.

Editar: decidí escribir mi propio uno también sólo por diversión: http://github.com/robertmassaioli/wrapping_number

+1

Por lo como sé, no hay un "estándar de la industria" para este tipo de cosas, como una biblioteca de Boost, si eso es lo que quieres decir. Pero como dijiste, debería ser lo suficientemente fácil implementar tal clase y sobrecargar a todos los operadores necesarios. –

+1

Usar un comentario en lugar de una respuesta porque 1) Nunca lo usé y 2) Todavía no es una biblioteca oficial de Boost pero: Boost.ConstrainedValue tiene un "wrapping_int" que se parece mucho a lo que está buscando: http: //student.agh.edu.pl/~kawulak/constrained_value/constrained_value/tutorial.html#constrained_value.tutorial.other_error_policies_for_bounded_objects –

+0

@Eric: Eso es exactamente lo que estaba buscando pero aún no está separado de las bibliotecas de impulso. Intenté buscar y no pude encontrar una implementación de referencia. Seguiré buscando, pero ¿sabes dónde está? –

Respuesta

2

Nunca lo he usado y todavía no es una biblioteca oficial de Boost, pero Boost.ConstrainedValue tiene un wrapping_int que se parece mucho a lo que está buscando.

A pesar de que aún no es una parte de Boost, que fue revisado y, IIUC, condicionalmente aceptado recientemente: http://lists.boost.org/boost-announce/2010/09/0265.php

La biblioteca está disponible en http://rk.dl.pl/f/constrained_value.zip

La documentación está en http://rk.dl.pl/r/constrained_value

+0

Escribí el mío también por diversión: http://github.com/robertmassaioli/wrapping_number –

4

No es más fácil de utilizar la función normalize?

int normalize(int val, int start, int end) 
{ 
    return (val - start) % (end - start) + start; 
} 


int ci = 4; 
assert(ci == 4); 
ci = normalize(ci + 3, 4, 8); 
assert(ci == 7); 
ci = normalize(ci + 2, 4, 8); 
assert(ci == 5); 
assert(ci == 13); 
+1

Eso es exactamente lo que estaba tratando de evitar porque no quiero tener que pensar realmente sobre la aplicación de la función normalizar (porque lo olvidaré eventualmente). Y la última afirmación también fallará, ¿no? –

+0

En realidad, creo que la última afirmación debe fallar, porque 13 no se define como un número de rango limitado, yo usaría assert (ci == cyclic_int <4,8> (13)); (la plantilla es conveniente aquí) – stefaanv

+0

@stefaanv: Creo que lo que está diciendo es que 13 debe ser congruente con 5 en el cíclico_int (4, 8) (es decir, incluye números enteros 4, 5, ...12), que es. Estoy de acuerdo con la noción de una plantilla ... proporciona una tipificación más fuerte. – andand

Cuestiones relacionadas