内部定义的类的运算符

时间:2012-06-25 10:03:08

标签: c++

template <class T>
class A {

    struct B {
         T a,b;
    }

    B& operator+ (B & x, B & y) {
        return B(x.a + y.a, x.b + y.b);
    }    

    int funcA (B & x, B & y){
        return (x + y).a;
    }
};

正如您可能猜到的,在编译期间,我得到“operator +必须采用零或一个参数”。 对。因为在运算符+中,“this”作为第一个参数传递。 因此,解决方案是将运算符定位在A类定义之外。 但是A的函数funcA使用operator +。所以它必须在A之前定义。但是operator +本身使用A中定义的B类,它是模板本身,B是依赖类。

解决方案是什么?

3 个答案:

答案 0 :(得分:3)

有一种方法可以在类的主体内定义一个自由函数:

struct B {
    T a,b;
    // the change from B& to B is nothing to do with defining
    // the function here, it's to avoid returning a dangling reference.
    friend B operator+ (B & x, B & y) {
        return B(x.a + y.a, x.b + y.b);
    }
};

对我来说,这是处理这种情况的最简单方法。

答案 1 :(得分:0)

除了@ SteveJessop的答案 - 这是最好的答案 - 如果运营商要成为会员,则必须是B的成员,而不是A的成员:

template <typename T>
class A {
public:
    struct B {
       T a,b;
       B(const T& x, const T& y) : a(x), b(y) {}
       B operator+(const B& rhs) const { return B(a + rhs.a, b + rhs.b); }
    };

    T funcA (B & x, B & y){
        return (x + y).a;
    }
};

答案 2 :(得分:0)

您可以将声明operator+转发到A之外,但funcA必须明确调用它。对于这种情况,您可能不希望在operator+之外定义A,但是因为您已经问过

  

因此,解决方案是将运算符定位在A类定义之外。 ......怎么样?

这个答案说明了它是怎么回事。

与molbdnilo一样,我也同意Steve Jessop的答案是最好的,这是你应该对这个问题采取的答案。

template <class T> class A;
template <class T>
typename A<T>::B operator + (typename A<T>::B &x, typename A<T>::B &y);

template <class T>
class A {
    template <class U>
    friend typename A<U>::B operator + (typename A<U>::B &x,
                                        typename A<U>::B &y);
    struct B {
         T a,b;
         B(T x, T y) : a(x), b(y) {}
    };
    static T funcA (B & x, B & y) {
        return ::operator+<T>(x, y).a;    
    }
public:
    A () {
        B a(0, 1);
        B b(1, 0);
        funcA(a, b);
    }
};

template <class T>
typename A<T>::B operator + (typename A<T>::B &x,
                             typename A<T>::B &y) {
    return typename A<T>::B(x.a + y.a, x.b + y.b);
}