Estoy en busca de una solución mediante el C++03 estándar (yo estoy obligado a usar esta versión de la norma durante varios años, sin embargo). Soluciones para C++11 también son bienvenidos, pero no va a ser «aceptado» como la respuesta a esta pregunta.

Lo que es una forma sencilla y concisa que pueda representar a un conjunto de constante, relacionada con valores de punto flotante como un solo tipo (similar a un enum) para garantizar la seguridad de tipos, sin incurrir en importantes gastos generales y aún me permiten operar en los valores como flotadores directamente?

El resultado final es que me gustaría ser capaz de hacer algo como lo siguiente:

enum FloatingPointEnum
{
   VALUE1 = 0.1234f,
   ...
   VALUEN = 0.6789f
};


float SomeFunction(FloatingPointEnum value)
{
    float new_value;
    /* perform some operation using "value" to calculate "new_value" */
    new_value = static_cast<float>(value); //<- a simplistic example
    return new_value;
}

Mientras yo puede pensar en varias soluciones, ninguna de ellas es tan limpia/simple/sencillo como yo quisiera y me imagino que alguien ya debe tener una solución elegante a este problema (sin embargo, me parece no puede encontrar uno en mi búsqueda).

EDICIÓN:

Me gustaría que la siguiente llamada a SomeFunction con un valor que no se especifica directamente como un valor del tipo enumerado a un error de compilación:

float nonEnumeratedValue = 5.0f
SomeFunction(nonEnumeratedValue);
  • de seguridad de tipo <-> «todavía me permiten operar en los valores como flotadores directamente» ¿Qué quieres decir? Si hay una conversión implícita de que tipo de float, no sería de tipo seguro. Si no hay ninguno, que no puede operar sobre ellos como floats directamente. ¿Podría darnos algunos ejemplos?
  • Ejemplos de código que te gustaría que fallan debido al tipo de seguridad sería de gran ayuda.

3 Comentarios

  1. 7

    alguien ya debe tener una solución elegante a este problema

    Hay un montón de problemas que no tienen solución elegante (y muchos de los que no tienen ninguna solución en absoluto). ¿Qué te hace pensar que este problema tiene uno? Esta suposición es muy defectuosa. Lo más cerca que se puede obtener es el uso de una clase contenedora.

    class FloatingPointEnum {
        float f;
        FloatingPointEnum(float arg) : f(arg) {}
    public:
        static const FloatingPointEnum Value1;
        static const FloatingPointEnum Value2;
        operator float() const { return f; }
    };
    const FloatingPointEnum FloatingPointEnum::Value1(0.1234f);
    const FloatingPointEnum FloatingPointEnum::Value2(0.6789f);
    • Gracias por su relativamente elegante respuesta. Con respecto a tu comentario sobre «alguien debe tener ya una solución elegante a este problema»: una y otra Vez, la comunidad de internet me ha mostrado una serie de elegantes soluciones a los problemas. Pensé que era mejor preguntar que pasar por el proceso de reinventar la rueda y partiendo de un cuadrado.
    • Que es bastante justo, y yo no voy a decir que se equivocaron a pedir, pero no es bueno asumir que existe una solución.
  2. 1

    En C++11 puede utilizar constexpr para lograr lo que desea.

    constexpr – especifica que el valor de una variable o función puede aparecer en expresiones constantes

    http://en.cppreference.com/w/cpp/language/constexpr

    Con constexpr definir una constante en tiempo de compilación. Esto sólo funciona para el literal tipos, tales como float. Ya que al mismo tiempo queremos

    float nonEnumeratedValue = 5.0f;
    SomeFunction(nonEnumeratedValue);

    a fallar, no podemos utilizar una simple typedef. En su lugar usamos Boost BOOST_STRONG_TYPEDEF.

    #include <boost/serialization/strong_typedef.hpp>
    
    BOOST_STRONG_TYPEDEF(float, FloatingPointEnum);
    constexpr float VALUE1 = 0.1234f;
    constexpr float VALUEN = 0.6789f;
    
    float SomeFunction(FloatingPointEnum value)
    {
      float new_value;
      /* perform some operation using "value" to calculate "new_value" */
      new_value = static_cast<float>(value); //<- a simplistic example
      return new_value;
    }

    Ahora usted puede llamar a la función sólo con las instancias de FloatingPointEnum. Por desgracia, la creación de instancias de sintaxis no es tan agradable ya

    FloatingPointEnum f {VALUEN};

    Alternativamente, usted puede simplemente utilizar el lenguaje de programación D, donde de punto flotante de las enumeraciones son compatibles y el siguiente código funciona como se esperaba:

    enum FloatingPointEnum
    {
       VALUE1 = 0.1234f,
       //...
       VALUEN = 0.6789f
    };
    
    
    float SomeFunction(FloatingPointEnum value)
    {
        float new_value;
        new_value = value; //No cast needed, welcome to D!
        return new_value;
    }

    Llamar SomeFunction con un float resultados en

    Error: function test.SomeFunction (FloatingPointEnum value) is not callable using argument types (float)
  3. 1

    Una posible alternativa de solución, no siempre es aplicable, pero muy limpio, es el uso de precisión fija.

    Imagine que tiene usted de la enumeración que contiene cierta distancia en metros

    enum DistancesMeter{
     A = 0.25,
     b = 0.05,
    };

    entonces usted puede simplemente cambiar el uso de mm

    enum DistancesMM{
     A = 250,
     b = 50,
    };

Dejar respuesta

Please enter your comment!
Please enter your name here