替换枚举以最大化编译时间检查的最佳方法
Best way to replace an enum to maximize compilation time checks
我有一个相当旧的应用程序来处理不同类型的货币。目前,货币存储在枚举中,例如:
enum CURRENCY {
EUR,
USD,
CNY
};
double convertMoney(CURRENCY in, CURRENCY out, double money_in) {
...
}
这工作得很好,除了这不是真正的类型安全:我还有其他包含注释的功能,例如WARNING: all inputs should have the same currency
.我的目标是尽可能用编译时检查替换这些注释中的大多数。我可以使用C++17和提升。
我想使用这样的std::variant
:
class EUR {};
class USD {};
class CNY {};
using CURRENCY = std::variant<EUR,USD,CNY>;
template<typename IN, typename OUT>
class Market {
public:
...
double convertMoney(double in) {
return in*rate;
}
private:
void updateRate() {
....
rate = some_value_fetched_at_runtime;
}
double rate;
};
int main() {
Market<EUR, USD> eur_usd;
Market<EUR, CNY> eur_cny;
std::vector<Market<CURRENCY,CURRENCY>> all_markets{eur_usd, eur_cny};
...
//do something
...
return 0;
}
但是,当然,这是行不通的,因为我正在尝试将不同类型的市场对象推入我的向量。
那么,综上所述,你们认为在现代C++中替换枚举的最佳方法是什么?如果使用std::variant
是正确的,那么解决上述问题的最佳方法是什么?
请注意:
- 我可以做类似
using Markets = std::variant<Market<EUR,USD>,Market<EUR,CNY>,...>
的事情,但这在实践中并不可行,因为我有大约 ~100 种类型的市场,这并没有真正提高可维护性。 - 我可以创建一个类
CURRENCY
并拥有CURRENCY
的EUR
、USD
、CNY
子类,但这会在运行时使用v-table,这将减少编译时检查的数量。如果有人能证明我相反,我对此持开放态度。 - 我所有的市场都是在我的源代码中定义的(我不需要在运行时动态地创建新的市场(,但汇率是动态变化的。
-
您可以将每种货币设置为单独的(模板(类,并在它们之间进行显式转换,就像它们在 ::std::chrono 或 ::boost::unit 中所做的那样。
template< CURRENCY VCurrencyId > class t_Sum { public: using t_Value = double; private: t_Value m_value{}; public: t_Sum(void) {} public: t_Sum(t_Sum const & other) : m_value{other.m_value} {} public: explicit t_Sum(t_Value const & value) : m_value{value} {} public: t_Sum & operator =(t_Sum const & other) { m_value = other.m_value; return(*this); } public: t_Value const & Get_Value(void) { return(m_value); } public: void Set_Value(t_Value const & value) { m_value = value; } }; template< CURRENCY VInputCurrencyId, CURRENCY VOutputCurrencyId > t_Sum< VOutputCurrencyId > Convert(t_Sum< VInputCurrencyId > in) { ... } using t_Eur = t_Sum< EUR >; using t_Usd = t_Sum< USD >; t_Eur euros{}; t_Usd bucks{euros}; // compile-time error, conversion required! // or you can add converting constructor
你可以做这样的事情:
enum class CURRENCY {
EUR = 0,
USD,
CNY,
LAST = CNY
};
template <CURRENCY cur> class Price;
// Class to handle convertion
class Market
{
public:
template <CURRENCY Out, CURRENCY In>
Price<Out> convertMoney(const Price<In>&);
void updateChange(CURRENCY in, CURRENCY out, double ratio);
private:
double ratios[int(CURRENCY::Last)][int(CURRENCY::Last)];
};
// Class to represent typed currency value
template <CURRENCY cur>
class Price
{
public:
explicit Price(double value) : value(value) {}
// should only be used when we want the value without the type
double getValue() const { return value; }
// operation which restrict same currency as
Price& operator +=(const Price&);
// ...
private:
double value;
};
相关文章:
- 在C#中处理C++指针而不使用unsafe的最佳方法
- 使用 gtest 框架在单元测试代码中检查目标对象的私有变量的最佳实践是什么?
- 检查特定目录中是否存在与文件匹配的 abc* 的最佳方法
- 替换枚举以最大化编译时间检查的最佳方法
- 检查 istream::read 和 istream::seekg 失败的最佳方法
- C++是检查多维数组中匹配项的最佳优化方法
- 检查C 11中的运算符的最佳方法
- 在C++中检查二重是否等于负无穷大的最佳方法
- 动态检查使用可变继承的类的类型的最佳方法是什么
- 检查浮点是否为整数的最佳方法
- 检查无符号整数是否没有索引的最佳实践
- 在我的解释器上为脚本代码实现语法检查器的最佳方式是什么
- 良好的程序设计/避免多重冗余检查的最佳实践(例如在C++中)
- 在c++中,检查给定用户配置文件是否处于活动状态或已删除的最佳方法是什么?
- 在QWebSockets客户端检查SSL证书有效性的最佳实践
- 在语句中设置条件检查格式"if"最佳方法
- 在C++中检查代理的最佳方法是什么?
- 在SystemC中检查信号是否有效的最佳方法是什么?
- 检查矢量是否排序的最佳算法
- 在C++中实现断言检查的最佳方法是什么