如何为 boost::variant 实现算术运算符,使其支持不同的数字类型

how to implement arithmetic operator for boost::variant so that it supports different numeric types

例如,如果我有以下变体和 static_visitor:

typedef boost::variant<long, int, float, double> DataType;

我希望它能起作用:

DataType x(1.2);
DataType y(100);
std::cout<<boost::apply_visitor(Multiply(), x, y)<<std::endl; // should return 120

遇到这样的访客:

struct Multiply : public boost::static_visitor<DataType>
{
    template<typename T, typename U>
    DataType operator()(const T& a, const U& b) const
    {
        // what to do here??
    }

    template<typename T>
    DataType operator()(const T& a, const T& b) const
    {
        return a * b;
    }
};

我如何做到这一点而不必在 Multiply 访问者中列出所有可能的类型组合?

我的建议:不要对同一类型进行特例处理,而是对可乘性进行特例处理:

struct Multiply : public boost::static_visitor<DataType> {
    template<typename T, typename U>
    static auto operator()(const T& a, const U& b) const
    -> decltype(DataType(a*b)){
        return a*b;
    }
    template<typename... Ts>
    static DataType operator()(const Ts... params) const {
        throw std::invalid_argument("can't multiply");
    }
};

变化:

  • 没有任何组合的特殊外壳有效。
  • 对任何不存在的组合抛出异常。
  • 现在static.

使用表达式-SFINAE 来决定。

不过,对于您的示例,它不会 return 120,因为二进制浮点数不能准确表示 1.2。