简体   繁体   English

产生算术运算结果类型的策略?

[英]Policy to produce the result type of an arithmetic operation?

Consider the following example: 考虑以下示例:

#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;
}

It is simple and does not exhibit any problem of design (at least I think). 它很简单,没有任何设计上的问题(至少我认为)。 Now consider that I want to be able to generate an operator+ (and all arithmetic operators) for classes with different property types. 现在考虑,我希望能够为具有不同属性类型的类生成一个operator+ (以及所有算术运算符)。 But there is no standard way to decide whether MyClass<Property1> + MyClass<Property2> should be a MyClass<Property1> or a MyClass<Property2> : so the good choice should be specified by the user. 但是没有确定MyClass<Property1> + MyClass<Property2>应该是MyClass<Property1>还是MyClass<Property2> :因此,好的选择应该由用户指定。 The question is the following: how to redesign the class (or anything else) to let the user provide a conversion strategy ? 问题如下:如何重新设计类(或其他任何类)以使用户提供转换策略? (I mean how would it be designed in the standard library or in boost ?) (我的意思是说它将如何在标准库或boost中进行设计?)

EDIT: To clarify, the result type of MyClass<Property1> + MyClass<Property2> cannot be automatically generated by the compiler. 编辑:澄清一下,编译器无法自动生成MyClass<Property1> + MyClass<Property2>的结果类型。 This policy should be specified by the user. 该策略应由用户指定。 But how to design that in a clean way ? 但是如何以一种干净的方式设计它呢?

Use type traits (as Kerrek SB pointed out in his comment). 使用类型特征(正如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 will only work if the type is implicitly convertable. std :: common_type仅在类型可以隐式转换时才起作用。 If there is no common type which is implicitly convertable or if the user wants a different one they can specialize CommonPropertyTypeTraits: 如果没有可以隐式转换的通用类型,或者用户想要其他类型,则可以专门使用CommonPropertyTypeTraits:

template<>
struct CommonPropertyTypeTraits<MyType,MyOtherType> {
    using type = SomeType;
} 

The body of your function would then be: 函数的主体将是:

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};
}

Note that this will give a pretty ugly error if there is not implicitly convertable common type and the user did not specialize the traits template. 注意,如果没有隐式可转换的通用类型并且用户没有专门化traits模板,这将带来一个非常丑陋的错误。 One could make a SFINAE test to make a better error: 可以进行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};
}

I'm still not quite certain what you ultimately want to use this for. 我仍然不确定您最终想使用它做什么。 If it is for dimensional analysis (ie tracking the types of different unit systems at compile time and making necessary conversions and issuing necessary errors) have a look at boost.Unit. 如果用于尺寸分析(即在编译时跟踪不同单位系统的类型并进行必要的转换并发出必要的错误),请查看boost.Unit。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM