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

8 c++ templates class operator-overloading

我正在尝试构建一个模板化的 num 类。这个类需要有一个公共属性 ,val和 type 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;
    }
};
Run Code Online (Sandbox Code Playgroud)

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

int main() {
    std::cout << Num<int>(1) + Num<double>(2.0);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

然而,程序的结果是现在3。而我期望它是3.0(类型double)。

Gui*_*cot 10

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

在您的代码中:

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

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

无论加法本身的类型如何,您的函数始终返回第一个操作数的类型。

您想要的是从添加中推断出该类型:

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

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

  • 在 c++14 及更高版本中,您不需要 `-&gt; Num&lt;decltype(val + other.val)&gt;` (2认同)

Evg*_*Evg 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};
}
Run Code Online (Sandbox Code Playgroud)

std::declval<T>()是否存在通用性,如果T和/或U不是默认可构造的。如果类型仅限于内置类型,例如intand double,则可以替换为T{}or T()

using R = decltype(T{} + U{});
Run Code Online (Sandbox Code Playgroud)

使用C++17 中的类模板参数推导,它可以进一步简化:

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