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

时间:2014-12-16 09:14:19

标签: c++ operators

是否有一种简单/智能的方法来实现缺少的运算符:‘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;
}

2 个答案:

答案 0 :(得分:1)

没有必要使用内部类。相反,你应该构建两个全局运算符,它们存在于这两个类之外:

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类型上创建这些函数模板,尽管只有更现代的编译器支持将模板函数设为朋友。

答案 1 :(得分:0)

我使用template template参数为我的问题找到了解决方案。这种方法允许我交替使用这两个类。但是,它需要对这两个类进行一些更改。对于myclassRef,我必须添加constget()并将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;
}