8

ストリーム演算子のオーバーロードに問題があり<<、解決策が見つかりません:

template<class T, unsigned int TN>
class NVector
{
    inline friend std::ostream& operator<< (
        std::ostream &lhs, const NVector<T, TN> &rhs);
};

template<class T, unsigned int TN>
inline std::ostream& NVector<T, TN>::operator<<(
    std::ostream &lhs, const NVector<T, TN> &rhs)
{
    /* SOMETHING */
    return lhs;
};

次のエラー メッセージが生成されます。

警告: フレンド宣言 'std::ostream& operator<<(std::ostream&, const NVector&)' は非テンプレート関数を宣言しています [-Wnon-template-friend]

エラー: 'std::ostream& NVector::operator<<(std::ostream&, const NVector&)' は 1 つの引数を取る必要があります

その問題を解決するには?

どうもありがとうございました。

4

1 に答える 1

16

コードには 2 つの異なる問題があります。1 つ目は、friend宣言 (警告が明確に示しているように、理解するのがあまり明確ではない可能性があります) が、テンプレート化されていない単一の関数をフレンドとして宣言していることです。つまり、テンプレートをインスタンス化すると、テンプレート化されていない関数がフレンドとしてNVector<int,5>宣言されます。std::ostream& operator<<(std::ostream&,NVector<int,5>)これは、フレンドとして提供したテンプレート関数を宣言することとは異なることに注意してください。

クラス定義内でフレンド関数を定義することをお勧めします。詳細については、この回答を参照してください。

template <typename T, unsigned int TN>
class NVector {
   friend std::ostream& operator<<( std::ostream& o, NVector const & v ) {
      // code goes here
      return o;
   }
};

または、他のオプションを選択することもできます。

  1. テンプレートをフレンドとして宣言しoperator<<ます (テンプレートのすべてのインスタンス化へのアクセスを許可します)。
  2. そのテンプレートの特定のインスタンス化をフレンドとして宣言する (書くのは面倒です) または
  3. publicprint( std::ostream& )メンバー関数を提供し、それを非フレンドの templated から呼び出すフレンドシップを完全に回避しoperator<<ます。テンプレート化されたクラス内で定義を提供するために、非テンプレート関数と友達になることを引き続き選択します。

2 つ目の問題は、左側の引数のクラスの外部で演算子を定義する場合、その演算子は自由な関数(クラスにバインドされていない) であるため、修飾されるべきではないということです。

template<class T, unsigned int TN>
inline std::ostream& operator<<(std::ostream &lhs, const NVector<T, TN> &rhs)
{
    /* SOMETHING */
    return lhs;
};
于 2012-05-28T16:27:14.227 に答える