我有一个相当老的应用程序,处理不同种类的货币。目前,货币存储在枚举中,例如:

enum CURRENCY {
  EUR,
  USD,
  CNY
};

double convertMoney(CURRENCY in, CURRENCY out, double money_in) {
   ...
}

这非常有效,除了不是真正安全的类型:我还有其他包含注释的函数,例如WARNING: all inputs should have the same currency。我的目标是在可能的情况下通过编译时间检查来替换大多数这些注释。我可以使用C++ 17和boost。

我想到使用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;
}

但是,当然,这将不起作用,因为我试图将不同类型的Market对象放入 vector 中。

因此,总而言之,你们认为替换现代C++中的枚举的最佳方法是什么?如果正确使用std::variant,解决上述问题的最佳方法是什么?

注意:
  • 我可以做类似using Markets = std::variant<Market<EUR,USD>,Market<EUR,CNY>,...>的操作,但是实际上这是不可行的,因为我有大约100种类型的市场,并且这并不能真正改善可维护性。
  • 我可以创建一个CURRENCY类,并具有EURUSDCNYCURRENCY子类,但这将在运行时使用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
    
  • 10-07 16:34
    查看更多