模板化的类运算符+重载返回类型

时间:2019-12-09 21:13:15

标签: c++ class templates operator-overloading

我正在尝试构建模板化的num类。此类需要具有类型为val的公共属性T,这是唯一的模板化参数。此外,如果提供一个值,则应使用该值初始化属性(val)。为此,我编写了以下代码:

#include <iostream>

template<class T>
class Num {
public: 
    T val;

    Num():val(0) { std::cout<<"default constr used"<<std::endl; }
    Num(T value):val(value) {std::cout<<"constr (T value) used"<<std::endl; }
    ~Num() { std::cout<<"destructor used"<<std::endl; }

    template<typename U>
    Num operator+(const Num<U>& other) {
        return val+other.value;
    }
};

此外,我创建了main()函数来测试程序,如下所示:

int main() {
    std::cout << Num<int>(1) + Num<double>(2.0);
    return 0;
}

但是程序的结果现在为3。而我希望它是3.0(类型为double)。

2 个答案:

答案 0 :(得分:10)

为此,您需要更改返回类型。

在您的代码中:

// vvv---- Means Num<T>
   Num operator+(const Num<U>& other) {
       return val + other.val;
   }

实际上,您可以在类模板中键入不带模板参数的类的名称,这在某种程度上等同于编写Num<T>

您的函数总是返回第一个操作数的类型,而不管加法本身的类型如何。

您要从加法推断出这种类型:

auto operator+(const Num<U>& other) -> Num<decltype(val + other.val)> {
    return val + other.val;
}

那样,根据C ++运算符规则,它始终是正确的返回类型。

答案 1 :(得分:9)

operator+应该相对于其参数是对称的。最好将其实现为自由函数而不是成员函数,以使这种对称性更加明显。

例如(使用C ++ 14返回类型推导):

template<class T, class U>
auto operator+(const Num<T>& x, const Num<U>& y) {
    using R = decltype(std::declval<T>() + std::declval<U>());
    return Num<R>{x.val + y.val};
}
如果std::declval<T>()和/或T无法默认构造,则{p> U就位于genericity。如果类型仅限于内置类型,例如intdouble,则可以将其替换为T{}T()

using R = decltype(T{} + U{});

在C ++ 17中使用class template argument deduction可以进一步简化:

template<class T, class U>
auto operator+(const Num<T>& x, const Num<U>& y) {
    return Num{x.val + y.val};
}