考虑以下示例:
#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>
的结果类型。该策略应由用户指定。但是如何以干净的方式设计呢?
答案 0 :(得分:0)
使用类型特征(正如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。