【问题标题】:C++ "Floating Point Enum"C++“浮点枚举”
【发布时间】:2013-10-16 16:05:13
【问题描述】:

我正在寻找使用 C++03 标准的解决方案(我被限制使用该版本的标准已有好几年了)。也欢迎 C++11 的解决方案,但不会被“接受”作为这个问题的答案。

什么是一种简单、简洁的方法,我可以将一组相关的常量浮点值表示为单一类型(类似于枚举),以确保类型安全而不会产生大量开销,并且仍然允许我对这些值进行操作直接浮动?

最终结果是我希望能够执行以下操作:

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

虽然我能想到几种解决方案,但没有一个像我想要的那样干净/简单/直截了当,而且我认为一定有人已经有了一个优雅的解决方案来解决这个问题(但我似乎无法在搜索中找到一个)。

编辑:

我希望使用未直接指定为枚举类型中的值的值对 SomeFunction 的以下调用无法编译:

float nonEnumeratedValue = 5.0f
SomeFunction(nonEnumeratedValue);

【问题讨论】:

  • type-safety “仍然允许我直接对值进行操作”你是什么意思?如果存在从该类型到float 的隐式转换,则它不是类型安全的。如果没有,则不能以floats 直接 对它们进行操作。你能提供一些例子吗?
  • 由于类型安全而无法编译的代码示例会很有帮助。

标签: c++ floating-point enumeration c++03


【解决方案1】:

一定有人已经对这个问题有一个优雅的解决方案

有很多问题没有优雅的解决方案(还有很多根本没有解决方案)。是什么让你认为这个问题有一个?这个假设是非常错误的。最接近的方法是使用包装类。

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

【讨论】:

  • 感谢您相对优雅的回答。关于您对“有人必须已经有了解决这个问题的优雅解决方案”的评论:互联网社区一次又一次地向我展示了许多优雅的问题解决方案。我认为问比重新发明轮子和从正方形开始的过程更好。
  • 这很公平,我不会说你问错了,但假设存在解决方案并不好。
【解决方案2】:

一种可能的替代解决方案,并不总是适用但非常干净,是使用固定精度。

让我们假设你有一个包含以米为单位的距离的枚举

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

那么你可以简单地切换到使用 mm

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

【讨论】:

    【解决方案3】:

    在 C++11 中,您可以使用 constexpr 来实现您想要的。

    constexpr - 指定变量或函数的值可以出现在常量表达式中

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

    使用constexpr,您可以定义一个编译时常量。这仅适用于文字类型,例如float。因为同时我们想要

    float nonEnumeratedValue = 5.0f;
    SomeFunction(nonEnumeratedValue);
    

    如果失败,我们不能使用简单的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;
    }
    

    现在您只能使用 FloatingPointEnum 的实例调用该函数。不幸的是,实例化语法不再那么好

    FloatingPointEnum f {VALUEN};
    

    或者,您可以简单地使用 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;
    }
    

    使用float 调用SomeFunction 会导致

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

    【讨论】:

      猜你喜欢
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-05
      • 2020-08-21
      相关资源
      最近更新 更多