0

我创建了一个模板类并想重载一个运算符 + (多次)。我通过以下方式做到这一点

template <typename T> class Polynomial;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

....

template <typename T>
class Polynomial {
    ....

    public:

    ....

    Polynomial operator +(const Polynomial& other) const {
       // impelementation
    }

    friend const Polynomial<T> operator + <> (const Polynomial<T>& poly, const T& scalar);

};

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
    // implementation
}

但是,我收到以下错误(对应于以“朋友”开头的行)

problem2.cpp:282:45: error: declaration of ‘operator+’ as non-function
problem2.cpp:282:45: error: expected ‘;’ at end of member declaration
problem2.cpp:282:47: error: expected unqualified-id before ‘&lt;’ token

按照 Raxvan 的建议,我更改了代码

模板类多项式;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

template <typename T>
ostream& operator <<(ostream& out, const Polynomial<T>& other);

....

template <typename T>
class Polynomial {
    ....

    public:

    ....

    friend ostream& operator << <> (ostream& out, const Polynomial<T>& other);

    Polynomial operator +(const Polynomial& other) const {
       // impelementation
    }

    template <typename NOT_T>
    friend const Polynomial<NOT_T> operator +(const Polynomial<NOT_T>& poly, const NOT_T& scalar);

};

template <typename T>
ostream& operator <<(ostream& out, const Polynomial<T>& other) {
    // implementation
}

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
    // implementation
}

在这段代码中,操作符 << 没有问题,就像操作符 + 一样。任何人都可以解释这种差异吗?

4

3 回答 3

2

问题很微妙。您的语法非常接近正确。我认为你的朋友声明应该是:

friend Polynominal<T> const operator+<T>( ... );

但 VC++ 和 g++ 都接受:

friend Polynominal<> const operator+<T>( ... );

当他们可以看到声明时:

template <typename T>
const Polynomial<T> operator+(const Polynomial<T>& poly, const T& scalar);

(我在标准中找不到任何东西来证明这一点,但由于 VC++ 和 g++ 都这样做,我想这是我错过的东西。)

这就是问题所在。命名空间范围的声明operator+被类内定义隐藏。编译器抱怨是因为operator+它发现(类中定义)本身不是模板(尽管它是类模板的成员)。

如果您对 没有问题operator<<,那是因为您没有同名的成员函数。

有几种方法可以解决这个问题。最简单的可能是结交所有的operator+朋友。与否:最常见的方法是operator+根据operator+=(在所有情况下都应该是成员)来实现。在这种情况下,operator+不必成为朋友。或者你根本不制作operator+模板,而是在你的类模板中定义它:

template <typename T>
class Polynomial
{
    friend Polynomial operator+( Polynomial const& lhs, Polynomial const& rhs )
    {
        //  ...
    }
    friend Polynomial operator+( Polynomial const& lhs, T const& rhs )
    {
        //  ...
    }
    friend Polynomial operator+( T const& lhs, Polynomial const& rhs )
    {
        //  ...
    }
}

(请注意,所定义的函数不是模板,而是单独的重载非模板函数,每个实例化一个Polynomial. 但结果最终是相同的。)

在这种情况下,您可能希望有一个由函数调用的成员函数operator+,它可以完成实际工作;您不希望像这样直接内联太多代码。

于 2013-11-06T11:07:41.357 回答
1

当您将函数标记为朋友时,您必须具有相同的定义,这包括上面使用的模板与另一种类型,而不是 T

template <typename T> class Polynomial;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

template <typename T>
class Polynomial {
public:

    template < class NOT_T> //must respect the deffinition from above
    friend const Polynomial<NOT_T> operator + (const Polynomial<NOT_T>& poly, const NOT_T& scalar);

};

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar)
{
    //...
}

编辑:

为了简化解释,我将函数更改为foobar说明声明中的差异:

template <typename T> class Polynomial;

template <typename T>
void bar(const Polynomial<T>& );

void foo(const Polynomial<float> & );//foo for speciffic float

template <typename T>
class Polynomial {
public:
    template <typename> //this is also valid declaration; 
    friend void bar(const Polynomial<T> & );
    //it just has to have template because it's a template functions declaration

    //not a valid declaration:
    //friend void bar <> (const Polynomial<T> & );

    //this declaration has no template;
    //it refers to a foo function specific to Polynomial<T> type
    //so if you use Polynomial<float> there must be a foo for floats
    friend void foo(const Polynomial<T> &);
};

template <class T>
void bar(const Polynomial<T>&)
{
}

void foo(const Polynomial<float> &)
{
}

void main()
{
    Polynomial<float>   pf;
    Polynomial<int>     pi;

    foo(pi);//error since there is not **foo** declared for int 
    foo(pf);//ok; we have **foo** for  Polynomial<float>

    bar(pf);
    bar(pi);//both ok since bar is templated function;
}

拉克斯万。

于 2013-11-06T10:15:16.557 回答
1

operator+是一个函数模板,为了使它成为朋友,你需要声明它完全包括模板参数,但是使用不同的模板参数,例如:

#include <iostream>

template <typename T> class Polynomial;

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar);

template <typename T>
class Polynomial {
    public:

    Polynomial operator +(const Polynomial& other) const {
      std::cout << "inline +" << std::endl;
    }

    // Here introduce a different type to indicate that this is a template...
    template <typename U>
    friend const Polynomial<U> operator + (const Polynomial<U>& poly, const U& scalar);

};

template <typename T>
const Polynomial<T> operator +(const Polynomial<T>& poly, const T& scalar) {
    std::cout << "friend +" << std::endl;
}

int main(void)
{
  Polynomial<int> f;

  f = f + 1;

  f = f + 1.; // this fails

  f = f + Polynomial<int>();
}
于 2013-11-06T10:18:30.400 回答