不同 c++ 类之间的运算符的简单实现

Simple implementation of operators between different c++ classes

本文关键字:运算符 实现 简单 之间 c++ 不同      更新时间:2023-10-16

有没有一种简单/聪明的方法来实现缺少的运算符:‘operator+’ (operand types are ‘myclassRef<int>’ and ‘myclass<int>’)这两个类?我知道我可以定义一个将这两种类型作为参数的函数。但是由于我正在实现几个应该将myclassmyclassRef类型作为参数的函数,我想以简单的方式做到这一点。

我一直在考虑将myclassRef作为myclass的内部类并使用隐式转换,但是这种方法(据我所知)要求使用这两种类型作为参数的所有函数都成为成员函数。

#include <iostream>
using namespace std;
template <class T>
struct myclass;
template <class T>
struct myclassRef
{
    T* i;
    myclassRef(myclass<T>* A)
    {
        i = &A->i;
    }
    operator myclass<T>()
    {
        return myclass<T>(*i);
    }
    T& get()
    {
        return *i;
    }
};
template <class T>
struct myclass
{
    T i;
    myclass() = default;
    myclass(const myclass&) = default;
    myclass(T _i) : i(_i) {}
    myclassRef<T> ref()
    {
        return myclassRef<T>(this);
    }
    T& get()
    {
        return i;
    }
    T get() const
    {
        return i;
    }
};
template <class T>
myclass<T>& operator+=(myclass<T>& lhs, const myclass<T>& rhs)
{
    lhs.get() += rhs.get();
    return lhs;
}
template <class T>
myclass<T> operator+(const myclass<T>& lhs, const myclass<T>& rhs)
{
    myclass<T> res(lhs);
    res += rhs;
    return res;
}
int main() {
    myclass<int> A(5);
    myclass<int> B(2);
    auto C = A + B;
    std::cout << C.i << std::endl;
    auto D = C.ref();
    A = D + B;
    return 0;
}
没有必要

使用内部类。相反,您应该构建两个全局运算符,它们存在于两个类之外,如下所示:

T operator+(const myclassRef<int>&, const myclass<int>&)

和过载

T operator+(const myclass<int>&, const myclassRef<int>&)

其中T是您决定的返回类型。如果这些函数中的任何一个需要类中的私有数据,则通过将以下声明放在类声明中,使这些函数成为两个类的friend

friend T operator+(const myclassRef<int>&, const myclass<int>&);
friend T operator+(const myclass<int>&, const myclassRef<int>&);

继续前进,您可能希望在myclassRef类型上制作这些函数模板,尽管只有更现代的编译器支持使模板函数成为朋友。

我使用template template参数为我的问题提出了解决方案。这种方法允许我互换这两个类。但是,它需要对这两个类进行一些更改。对于myclassRef,我必须添加get()const版本,并将myclass设置为friend class。对于myclass,我必须定义一个新的构造函数,即myclass(const myclassRef<T>& r) .当然,还要更改两个运算符的参数。

更改在代码中标记。

#include <iostream>
using namespace std;
template <class T>
struct myclass;
template <class T>
struct myclassRef
{
    T* i;
    myclassRef(myclass<T>* A)
    {
        i = &A->i;
    }
    T& get()
    {
        return *i;
    }
    T get() const // Added as part of the answer
    {
        return *i;
    }
    friend class myclass<T>; // Added as part of the answer
};
template <class T>
struct myclass
{
    T i;
    myclass() = default;
    myclass(const myclass&) = default;
    myclass(T _i) : i(_i) {}
    myclass(const myclassRef<T>& r) : i(*r.i) {} // Added as part of the answer
    myclassRef<T> ref()
    {
        return myclassRef<T>(this);
    }
    T& get()
    {
        return i;
    }
    T get() const
    {
        return i;
    }
};
template <template <class> class Mlhs, template <class> class Mrhs, class T>  // Added as part of the answer
Mlhs<T>& operator+=(Mlhs<T>& lhs, const Mrhs<T>& rhs)
{
    lhs.get() += rhs.get();
    return lhs;
}
template <template <class> class Mlhs, template <class> class Mrhs, class T>  // Added as part of the answer
myclass<T> operator+(const Mlhs<T>& lhs, const Mrhs<T>& rhs)
{
    myclass<T> res(lhs);
    res += rhs;
    return res;
}
int main() {
    myclass<int> A(5);
    myclass<int> B(2);
    auto C = A + B;
    std::cout << C.i << std::endl;
    auto D = C.ref();
    A = D + B;
    std::cout << A.i << std::endl;
    return 0;
}