C ++ «Перечисление с плавающей точкой»

Я ищу решение с использованием стандарта 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);

5

Решение

кто-то уже должен иметь элегантное решение этой проблемы

Есть много проблем, которые не имеют элегантного решения (и многие из них не имеют решения вообще). Что заставляет вас думать, что эта проблема есть? Это предположение очень ошибочно. Самое близкое, что вы можете получить, это использовать класс-оболочку.

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

Другие решения

В C ++ 11 вы можете использовать constexpr добиться того, что вы хотите.

constexpr — указывает, что значение переменной или функции может появляться в константных выражениях

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

С constexpr Вы определяете постоянную времени компиляции. Это работает только для литеральных типов, таких как float, Так как в то же время мы хотим

float nonEnumeratedValue = 5.0f;
SomeFunction(nonEnumeratedValue);

потерпеть неудачу, мы не можем использовать простой typedef, Вместо этого мы используем 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;
}

Теперь вы можете вызывать функцию только с экземплярами 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;
}

призвание SomeFunction с float результаты в

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

Возможное альтернативное решение, не всегда применимое, но очень чистое, заключается в использовании фиксированной точности.

Давайте представим, что у вас есть перечисление, содержащее некоторое расстояние в метрах

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

тогда вы можете просто переключиться на использование мм

enum DistancesMM{
A = 250,
b = 50,
};
1
По вопросам рекламы [email protected]