考虑以下示例:
#include <iostream>
#include <string>
template <class Property>
struct MyClass
{
double _data;
};
template <class Property>
inline MyClass<Property> operator+(const MyClass<Property> lhs,
const MyClass<Property> rhs)
{
return {lhs._data + rhs._data};
}
int main()
{
MyClass<std::string> a{1.5};
MyClass<std::string> b{2.5};
MyClass<std::string> c = a + b;
std::cout<<c._data<<std::endl;
return 0;
}
它很简单,没有任何设计问题(至少我认为是这样)。现在考虑我希望能够生成一个 operator+
(以及所有算术运算符)用于具有不同属性类型的类。但是没有标准的方法来决定是否MyClass<Property1> + MyClass<Property2>
应该是 MyClass<Property1>
或 MyClass<Property2>
: 所以好的选择应该由用户指定。问题如下:如何重新设计类(或其他任何东西)让用户提供转换策略? (我的意思是它在标准库或 boost 中如何设计?)
编辑:澄清一下,MyClass<Property1> + MyClass<Property2>
的结果类型不能由编译器自动生成。该策略应由用户指定。但是如何以干净的方式设计它呢?
最佳答案
使用类型特征(正如 Kerrek SB 在他的评论中指出的那样)。
template<typename T, typename U>
struct CommonPropertyTypeTraits : std::common_type<T,U>{}; //default version works if the types have a common type
std::common_type 仅在类型可隐式转换时才有效。如果没有可隐式转换的通用类型,或者如果用户想要不同的类型,他们可以专门化 CommonPropertyTypeTraits:
template<>
struct CommonPropertyTypeTraits<MyType,MyOtherType> {
using type = SomeType;
}
你的函数体将是:
template <class Property1, class Property2>
inline MyClass<typename CommonPropertyTypeTraits<Property1,Property2>::type> operator+(const MyClass<Property1> lhs, const MyClass<Property2> rhs)
{
return {lhs._data + rhs._data};
}
请注意,如果没有隐式可转换的通用类型并且用户没有专门化特征模板,这将产生一个非常丑陋的错误。可以进行 SFINAE 测试以做出更好的错误:
template <class Property1, class Property2, typename=typename CommonPropertyTypeTraits<Property1,Property2>::type>
inline MyClass<typename CommonPropertyTypeTraits<Property1,Property2>::type> operator+(const MyClass<Property1> lhs, const MyClass<Property2> rhs)
{
return {lhs._data + rhs._data};
}
我仍然不太确定您最终想用它做什么。如果是维度分析(即在编译时跟踪不同单位系统的类型并进行必要的转换并发出必要的错误),请查看 boost.Unit。
关于c++ - 生成算术运算结果类型的策略?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22269208/