Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ "Floating Point Enum"

I am looking for a solution using the C++03 standard (I am constrained to using this version of the standard for several years yet). Solutions for C++11 are also welcome, but will not be "accepted" as the answer to this question.

What is a simple, concise way that I can represent a set of related constant floating point values as a single type (similar to an enum) to ensure type-safety without incurring significant overhead and still allow me to operate on the values as floats directly?

The end result is that I would like to be able to do something like the following:

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

While I can think of several solutions, none of them are as clean/simple/straightforward as I would like and I figure that someone must already have an elegant solution to this problem (yet I cannot seem to find one in my searching).

EDIT:

I would like the following call to SomeFunction with a value that is not specified directly as a value from the enumerated type to fail to compile:

float nonEnumeratedValue = 5.0f
SomeFunction(nonEnumeratedValue);
like image 891
statueuphemism Avatar asked Oct 16 '13 16:10

statueuphemism


3 Answers

someone must already have an elegant solution to this problem

There are lots of problems that have no elegant solution (and many that have no solution at all). What makes you think this problem has one? The closest you can get is to use a wrapper class.

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);
like image 149
Puppy Avatar answered Oct 13 '22 03:10

Puppy


A possible alternative solution, not always applicable but very clean, is to use fixed precision.

Lets imagine you have you enum containing some distance in meters

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

then you may simply switch to use mm

enum DistancesMM{
 A = 250,
 b = 50,
};
like image 38
mauro Avatar answered Oct 13 '22 03:10

mauro


In C++11 you can use constexpr to achieve what you want.

constexpr - specifies that the value of a variable or function can appear in constant expressions

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

With constexpr you define a compile-time constant. This only works for literal types, such as float. Since at the same time we want

float nonEnumeratedValue = 5.0f;
SomeFunction(nonEnumeratedValue);

to fail, we cannot use a simple typedef. Instead we use Boost’s 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;
}

Now you can call the function only with instances of FloatingPointEnum. Unfortunately, the instantiation syntax is not so nice anymore

FloatingPointEnum f {VALUEN};

Alternatively, you can simply use the D programming language, where floating point enums are supported and the following code works as expected:

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

Calling SomeFunction with a float results in

Error: function test.SomeFunction (FloatingPointEnum value) is not callable using argument types (float)
like image 2
Henri Menke Avatar answered Oct 13 '22 04:10

Henri Menke