简体   繁体   English

模板类自动类型转换的运算符重载

[英]Operator Overload for Template Class Auto Type Conversion

I have a template class for which I'm overloading operator+ , but need it to potentially return a different data type than what the class is instantiated for. 我有一个模板类,我正在重载operator+ ,但需要它可能返回一个不同于实例化类的数据类型。 For example, the following snippet performs the standard mathematical definition of either vector*vector (inner product), vector*scalar, or scalar*vector. 例如,以下片段执行vector * vector(内积),vector * scalar或scalar * vector的标准数学定义。 To be specific, let's say I have a Vector<int> and the scalar is of type double -- I want to return a double from the "vector*scalar" operator+ function. 具体来说,假设我有一个Vector<int> ,标量是double类型 - 我想从“vector * scalar” operator+函数返回一个double。

I'm pretty sure I'm missing some template<class T> statements for the friend functions(?), but this snippet isn't meant to compile. 我很确定我缺少一些朋友函数(?)的template<class T>语句,但是这个片段并不打算编译。

template<class T>
class Vector
{
private:
    std::vector<T> base;

public:
    friend Vector operator*(const Vector& lhs, const Vector& rhs);  // inner product    
    Vector<T> operator*(const T scalar);  // vector*scalar   
    friend Vector operator*(const T scalar, const Vector& rhs);  // scalar*vector
};

template<class T>
Vector<T> operator*(const Vector<T>& lhs, const Vector<T>& rhs)  // inner product
{
    assert( lhs.base.size() == rhs.base.size() );

    Vector result;
    result.base.reserve(lhs.base.size());
    std::transform( lhs.base.begin(), lhs.base.end(), rhs.base.begin(), std::back_inserter(result.base), std::multiplies<T>() );

    return result;
}

template<class T>
Vector<T> Vector<T>::operator*(const T scalar)  // vector*scalar
{
    Vector result;
    result.base.reserve(base.size());

    std::transform( base.begin(), base.end(), std::back_inserter(result.base), std::bind1st(std::multiplies<T>(), scalar) );

    return result;
}

template<class T>
Vector<T> operator*(const T scalar, const Vector<T>& rhs)  // scalar*vector
{
    Vector result;
    result.base.reserve(rhs.base.size());

    std::transform( rhs.base.begin(), rhs.base.end(), std::back_inserter(result.base), std::bind1st(std::multiplies<T>(), scalar) );

    return result;
}

The friend declaration should look like this: 朋友声明应如下所示:

template<class S>
class Vector
{
private:
    std::vector<S> base;

public:
    template<class T> friend T operator*(const Vector<T>& lhs, const Vector<T>& rhs);  // inner product    
    template<class T> friend Vector<T> operator*(const T scalar);  // vector*scalar   
    template<class T> friend Vector<T> operator*(const T scalar, const Vector<T>& rhs);  // scalar*vector
};

And the rest of the code like this: 其余代码如下:

template<class T>
T operator*(const Vector<T>& lhs, const Vector<T>& rhs)  // inner product
{
    assert( lhs.base.size() == rhs.base.size() );

    Vector<T> result;
    result.base.reserve(lhs.base.size());
    std::transform( lhs.base.begin(), lhs.base.end(), rhs.base.begin(), std::back_inserter(result.base), std::multiplies<T>() );

    return result;
}

template<class T>
Vector<T> operator*(const Vector<T>& lhs, const T scalar)  // vector*scalar
{
    return scalar*lhs;
}

template<class T>
Vector<T> operator*(const T scalar, const Vector<T>& rhs)  // scalar*vector
{
    Vector<T> result;
    result.base.reserve(rhs.base.size());

    std::transform( rhs.base.begin(), rhs.base.end(), std::back_inserter(result.base), std::bind1st(std::multiplies<T>(), scalar) );

    return result;
}

I guess what you want is to return a Vector with the value type being the type returned by the per-component operation, which is not necessarily the type of the scalar. 我想你想要的是返回一个Vector,其值类型是每个组件操作返回的类型,它不一定是标量的类型。

For example: 例如:

Vector<int>    * int    -> Vector<int>
Vector<int>    * double -> Vector<double>
Vector<double> * int    -> Vector<double>
Vector<char>   * float  -> Vector<float>

etc. 等等

For this, you should define the two input types separately, let's say T1 and T2 (and one or two of the operands is a Vector of it). 为此,您应该分别定义两种输入类型,例如T1T2 (并且一个或两个操作数是它的Vector )。 You don't want to simply use the scalar type (for vector * scalar, or scalar * vector operation) as the result, otherwise it might be converted (see my 3rd example: The result would then be Vector<int> . 您不希望简单地使用标量类型(对于矢量*标量或标量*向量运算)作为结果,否则它可能会被转换(请参阅我的第3个示例:结果将是Vector<int>

The above can be done using decltype to find the third (result) type. 以上可以使用decltype来查找第三个(结果)类型。

For simplicity, define the operator as a non-member: 为简单起见,将运算符定义为非成员:

template<typename T1, typename T2, typename T3 = decltype(std::declval<T1>() * std::declval<T2>())>
Vector<T3> operator*(const Vector<T1>& lhs, const T2 & scalar)  // inner product
{
    Vector<T3> result;
    //...
    return result;
}

The interesting part is 有趣的是

T3 = decltype(std::declval<T1>() * std::declval<T2>())

Here, we find the type T3 using the other two types T1 and T2 . 在这里,我们使用另外两种类型T1T2找到T3类型。 First, we construct two values with unimportant value (the std::declval function is a helper function returning the type given as a template parameter). 首先,我们用不重要的值构造两个值( std::declval函数是一个辅助函数,返回给定为模板参数的类型)。 Then we multiply those values, but again the result is unimportant; 然后我们将这些值相乘,但结果再次不重要; we're only interested in the type. 我们只对这种类型感兴趣。 That's what the third part does: decltype gives you the type of the expression (without evaluating it). 这就是第三部分的作用: decltype为您提供表达式的类型(不进行评估)。

The other operators can be implemented analogous. 其他运营商可以类似地实施。

In order to make those operators friends, you need the syntax 为了使这些运营商成为朋友,您需要语法

template<...> friend ...

as seen in Danvil's answer . 正如丹维尔的回答所示

You can add more template parameters as such: 您可以添加更多模板参数:

template<class T, class S>
Vector<S> Vector<T>::operator*(const S scalar)

and make sure you use S for the scalar type and T for the vector element type in the correct places in the function body. 并确保在标量类型中使用S ,在函数体中的正确位置使用T作为向量元素类型。

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

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