C++ "Floating Point Enum" - c++

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

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

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

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)

Related

Creating dynamic data-type in C++

I'm creating an interpreter of a particular language in C++. After creating a parser, implementing scope resolution etc., the only problem I have is implementing dynamically typed variables.
Following some general advice scattered around, I created VarData and VarType structs:
union VarData{
int IntData;
char CharData;
double DoubleData;
};
enum class VarType {
Int,
Char,
Double
};
and a variable struct (it is obviously incomplete):
struct Variable {
VarData data;
VarType type;
template<typename T>
void operator =(T val) {
std::string name = typeid(T).name();
if (name == "char") {
data.CharData = val;
type = VarType::Char;
}
else if (name == "int") {
data.IntData = val;
type = VarType::Int;
}
else if (name == "double") {
data.DoubleData = val;
type = VarType::Double;
}
}
};
And this actually kind of works, for instance in this sample code, all assigned values are correctly stored:
int main() {
Variable a;
a = '5'; // a.type is now VarType::Char
a = 57; // a.type is now VarType::Int
a = 8.032; // a.type is now VarType::Double
}
The problem I have is that if I want to use the Variable struct, I need operator overloads for all common operators (+, -, /, * etc.), each of which needs to cover all possible pairs of types Variable can take. For instance,
Variable operator + (Variable& v1, Variable& v2) {
if (v1.type == VarType::Char && v2.type == VarType::Char)
//return Variable of type int
else if (v1.type == VarType::Double && v2.type == VarType::Int)
// return Variable of type double
else if (...)
}
Is there any other (not involving millions of nested if statements) method of doing that?
Sorry if my question is not exactly clear, I will be happy to provide additional explanation.
One way to handle all the different possible type combinations could be to use double dispatch to execute the operation based on the types involved.
Double dispatch would simplify the determination of what variant of the operation to execute. This means a lot of if less, leaving either to some clever combination of overload override or a dispatch table the duty to mechanically find the suitable operation. However, it would not really be a mastery of the combinatorial explosion.
Another more effective way would be to apply some systematic type promotion rules. For example if you want to combine in one operation an integer and a float, you'd convert everything to float before performing the operation.
If you use the interpreter pattern, you could have a template method pattern to manage the type promotion before invoking the suitable operator overload for two values of the same type.
Unrelated but important: you need to be aware that the typeid() is not a standardized value. So "int", "double", etc... are a nice implementation, but other strings might be used for other compilers. This makes your code non-portable

creating a literal for a Point - C++

I am trying to do a simple library where the object is a point on the xy-axis.
I want to be able to use literals like this:
Point a = (3,4);
where (3,4) is a point literal.
I read about user defined literals, but (as I understood) this seems to be impossible.
May be "(3,4)"_P is possible as I understand it.
However, I found on this page interesting use of user defined literals as follows:
#include <iostream>
#include <complex>
int main()
{
using namespace std::complex_literals;
std::complex<double> c = 1.0 + 1i;
std::cout << "abs" << c << " = " << abs(c) << '\n';
}
I can under stand the part 1i as a user defined literal, but not the whole thing 1.0 + 1i.
What I am missing, and what is the nearest possible way of getting a literal similar to (x,y) without using ".
As Some programmer dude shows, the best way is to use uniform initialization.
However, just for the fun of it, you can (sort of) do this with User Defined Literals. My idea is to to have 2 literals for each coordinate and overload operator+ between them to create the point.
Remember, this is just for fun, don't use this in a real code:
struct Px { int x; };
struct Py { int y; };
struct Point {
int x;
int y;
};
constexpr auto operator""_px(unsigned long long x) -> Px { return Px{(int)x}; }
constexpr auto operator""_py(unsigned long long y) -> Py { return Py{(int)y}; }
constexpr auto operator+(Px x, Py y) -> Point { return Point{x.x, y.y}; }
then you can have:
auto p = 3_px + 4_py; // p is deduced to type `Point`
Of course this is just a rough framework. Read this great article to learn more about UDLs. You would need to deal with the narrowing conversion in a better way and propper use namespaces to make it a better solution.
As a bonus, you could also use operator, to create a syntax more appropriate to what you had in mind. But, don't do this, as overloading operator, is just evil:
auto operator,(Px x, Py y) -> Point { return Point{x.x, y.y}; }
auto p = (2_px, 1_py); // p is deduced to type `Point`
You can't make up literals on your own, only create suffixes for literals. Like the shown 1i or the standard language f as in 1.0f. (See e.g. this user-defined literal reference for more information.)
What you can to is to use uniform initialization doing something like
Point a = { 3, 4 }; // note the use of curly-braces
Depending on what Point is you might need to add a suitable constructor to make it work.
You have 3 options
Point p = { 1,2 };
Point p2{ 1,2 };
Point p3(1,2);

Getting same constants to work for floats or doubles

I am enabling a large code base to alternate between single and double floating point precision via a single typedef. At present, my code is double-oriented:
double foo(double input)
{
return 1.0/input;
}
A naive switch to programmer-specified precision looks like this:
#ifdef _USE_DOUBLES
typedef double fpType;
#else
typedef float fpType;
#endif
fpType foo(fpType input)
{
return 1.0/input;
}
Obviously, the "1.0" causes a compiler warning. My best solution so far is to treat every constant thus:
fpType foo(fpType input)
{
return fpType(1.0)/input;
}
Is there any possibility that the explicit POD constructor invocation will actually be performed at runtime, thus charging me a speed penalty just for solving compiler warnings? I suspect not, since a compile time rewrite from "fType(CONSTANT)" to "CONSTANTf" seems trivial. But I want to make absolutely sure. I use VC, but I want to know about C++ compilers in general.
Also, is there a more elegant solution than mine? The fpType() invocations get ugly when lots of constants feature in one expression:
fpType someVal = fpType(1.0)/(someOtherVal+fpType(0.5))*(someVal
/fpType(7.66))*fpType(43.33);
I expect there are compiler-specific approaches to this problem, but I seek a compiler-agnostic one, if it exists. Naturally, I would look to warning suppression only as a last resort, perhaps not at all.
[EDIT]
I wrote this question misunderstanding "direct initialization", which is explained at Constructor Initialization of primitive data types in CPP.
You may try C++11 user defined literals:
#include <iostream>
#ifdef USE_DOUBLES
constexpr double operator"" _f (double value)
{
return value;
}
#else
constexpr float operator"" _f (double value)
{
return value;
}
#endif /*USE_DOUBLE*/
using namespace std;
int main()
{
cout << 1.2_f << endl;
}
For the literal constants, you could use float type. The conversion to double will happen without any compiler warnings.
fpType foo(fpType input)
{
return 1.0f/input;
}

Passing Enums as a Float

I have a question concerning enumerations and floats.
I'm trying to pass an enum as a float is this possible?
Here's an outline of the code:
enum
{
none = 0,
small,
medium,
large,
} enumSize;
class size
{
float footsize = 0.0;
}
void setSize(size &Size, float value)
{
Size.footsize = value;
}
int main()
{
size Size;
setSize(Size, enumSize);
}
However I cannot call setSize(Size, enumSize) since as far as I know enums can only be ints and cant be casted to be a float? If that's the case is there a way to make it a float with my current setup?
If my layout is slightly confusing let me know and I'll try to address any confusion best I can.
Of course ints can be cast to floats, but an enum is not an appropriate tool for this. Just use const floats.
By the way, your code doesn't compile for several other reasons as well.
There's no casting involved, just a conversion. Ordinary enums are integer values and when you pass one of them to a function that takes a float the value gets converted to float.
enum enumSize {
none,
small,
medium,
large
};
void f(float);
void g() {
f(small);
}

Why can't I increment a variable of an enumerated type?

I have a enumerated type StackID, and I am using the enumeration to refer to an index of a particular vector and it makes my code easier to read.
However, I now have the need to create a variable called nextAvail of type StackID. (it actually refers to a particular stackID ). I tried to increment it but in C++, the following is illegal:
nextAvail++;
Which sort of makes sense to me ... because there's no bounds checking.
I'm probably overlooking something obvious, but what's a good substitute?
I also want to link to this question.
I'm probably overlooking something obvious, but what's a good substitute?
Overloading operator++:
// Beware, brain-compiled code ahead!
StackID& operator++(StackID& stackID)
{
#if MY_ENUMS_ARE_CONTIGUOUS && I_DO_NOT_WORRY_ABOUT_OVERFLOW
return stackID = static_cast<StackID>( ++static_cast<int>(stackID) );
#else
switch(stackID) {
case value1 : return stackID = value2;
case value2 : return stackID = value3;
...
case valueN : return stackID = value1;
}
assert(false);
return stackID; // some compilers might warn otherwise
#endif
}
StackID operator++(StackID& stackID, int)
{
StackID tmp(stackID);
++stackID;
return tmp;
}
Because enumerations do not have to be contiguous. E.g. take this example:
enum Colors {
cRed, // = 0
cBlue, // = 1
cGreen = 3
}
What should happen in this scenario?
Colors color = cBlue;
Colors other = color++;
Should other be cGreen or should it be 2. In that case it's not a valid enumeration member anymore. What about this?
Colors color = cGreen;
Colors other = color++;
Should other be cRed (wrap around) or 4?
As you can see, being able to increment enumeration values introduces a whole lot of questions and complicates the simple mechanism that they intend to be.
If all you care about is the integer value being incremented, then simply cast to int and increment that.
Casting back and forth to/from int is of course the obvious solution, then you make clear that you understand that the addition is happening "outside" the enum:
nextAvail = static_cast<StackID>(static_cast<int>(nextAvail) + 1);
Why not store nextAvail as an int instead if you're going to do arithmetic operations on it?
Another option would be to wrap the enum in your own type and overload operator ++ for it (which also could wrap around or something for instance).
An enumeration is semantically supposed to represent a set of distinct related, values.
So you could have
enum Colour {RED, GREEN, BLUE};
But that should be equivalent to:
enum Colour {GREEN, BLUE, RED};
The problem is that if you increment an enum then those representations are not the same. GREEN++ in the first case is not the same as GREEN++ in the second.
Making your program dependent on the declaration of the enum is a recipe for disaster - maintainers may assume that the order of the enum doesnt matter, introducing many silent bugs.
Very Simple:
nextAvail = (StackID)(nextAvail + 1);
Enums are going to be type int, so you can cast them. Is this what you're trying to do?
int ndx = (int) StackID.SomeValue;
...
++ndx;
This is going to make someone very confused down the line, of course.
It occurs to me that you're using an enum where you should be using const, or even #define. enum is most appropriate when you have arbitrary values (where the exact value is not meaningful).
I've overloaded the ++/-- operator in this way:
enum STATE {STATE_1, STATE_2, STATE_3, STATE_4, STATE_5, STATE_6};
// Overload the STATE++ operator
inline STATE& operator++(STATE& state, int) {
const int i = static_cast<int>(state)+1;
state = static_cast<STATE>((i) % 6);
return state;
}
// Overload the STATE-- operator
inline STATE& operator--(STATE& type, int) {
const int i = static_cast<int>(type)-1;
if (i < 0) {
type = static_cast<STATE>(6);
} else {
type = static_cast<STATE>((i) % 6);
}
return type;
}
With respect to oprator++, $5.2.6/1 states- "The type of the operand shall be an arithmetic type or a pointer to a complete object type."
StackID does not fit the bill here. It is of enumeration type.
One option is like this
$5.7/1 - "For addition, either both operands shall have arithmetic or enumeration type, or one operand shall be a pointer to a completely defined object type and the other shall have integral or enumeration type."
enum Possibility {Yes, No, Maybe};
Possibility operator++(Possibility const& r){
return Possibility(r + 1); // convert r to integer, add 1, convert back to Enum
}
int main(){
Possibility p = Yes;
Possibility p1 = ++p;
}
I'm quite happy with this C plus C++ solution for a for loop incrementing an enum.
for (Dwg_Version_Type v = R_INVALID; v <= R_AFTER; v++)
=>
int vi;
for (Dwg_Version_Type v = R_INVALID;
v <= R_AFTER;
vi = (int)v, vi++, v = (Dwg_Version_Type)vi)
The other solutions here are not C backcompat, and quite large.