简体   繁体   English

C ++“浮点枚举”

[英]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). 我正在寻找使用C ++ 03标准的解决方案(我被限制使用这个版本的标准已有好几年了)。 Solutions for C++11 are also welcome, but will not be "accepted" as the answer to this question. C ++ 11的解决方案也是受欢迎的,但不会被“接受”作为这个问题的答案。

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: 我希望以下对SomeFunction的调用,其值不是直接指定为枚举类型的值,无法编译:

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? 是什么让你认为这个问题有一个? This assumption is very faulty. 这个假设非常错误。 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);

In C++11 you can use constexpr to achieve what you want. 在C ++ 11中,您可以使用constexpr来实现您想要的功能。

constexpr - specifies that the value of a variable or function can appear in constant expressions constexpr - 指定变量或函数的值可以出现在常量表达式中

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

With constexpr you define a compile-time constant. 使用constexpr您可以定义编译时常量。 This only works for literal types, such as float . 这仅适用于文字类型,例如float Since at the same time we want 既然我们想要的话

float nonEnumeratedValue = 5.0f;
SomeFunction(nonEnumeratedValue);

to fail, we cannot use a simple typedef . 失败,我们不能使用简单的typedef Instead we use Boost's BOOST_STRONG_TYPEDEF . 相反,我们使用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;
}

Now you can call the function only with instances of FloatingPointEnum . 现在,您只能使用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: 或者,您可以简单地使用D编程语言,其中支持浮点枚举,并且以下代码按预期工作:

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 使用float调用SomeFunction导致

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

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 然后你可以简单地切换到使用mm

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM