如何为 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。
例如,如果我有以下变体和 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。