0
//cannot declare operator<<(...) here: 
//forward declarations: 
class External; 

template<class T, class Y> 
class External::Internal; 

template<class T, class Y> 
std::ostream& operator<<(std::ostream& out, const External::Internal<T,Y>&); 

class External 
{ 
    template<class T, class Y> 
    class Internal 
    {}; 

    Internal data_; 

    void print() { 
     /*out is a std::ostream*/ 
     out << data_; 
    } 
}; 

template<class T, class Y> 
std::ostream& operator<<(std::ostream& out, const External::Internal<T,Y>&) 
{ } 

のための演算子を<<宣言するためにはどうすればInternalためoperator<<を実装したいんが、私はExternalからこのオペレータコールを使用しようとする問題がある。この演算子であるときには、この演算子を見ていませんこのクラスの定義の下で宣言され、このクラス定義の上にこの演算子を宣言する方法はないようです。内部クラス

+0

なぜISN」 「内部」は適切に修飾されていますか? –

答えて

1

あなたは、友人としてInternal<>::operator<<を定義する方法を求めている場合:

class External 
{ 
    template<class T, class Y> 
    class Internal 
    { 
    friend std::ostream& operator <<(std::ostream& out, const Internal&) 
    { 
     // impl 
     return out; 
    } 
    }; 

    Internal<Foo, Bar> data_; 

public: 
    void print() const 
    { 
    /*out is a std::ostream*/ 
    out << data_; 
    } 
}; 
+0

@ildjarnありがとうございます。しかし、コンパイルするには、オペレータ – smallB

+2

@smallBからテンプレートを削除する必要があります: "*しかし、コンパイルするには、テンプレートを演算子から削除する必要があります。"演算子はテンプレートなので、テンプレートとして定義する必要があります。これはそのままの状態でコンパイルされます。 – ildjarn

+0

@ildjarnはVS2010 sp1でコンパイルしたくありませんでした。 – smallB

1
template<class T, class Y> 
std::ostream& operator<<(std::ostream& out,const External::Internal<T, Y>&) 
               ^^^^^^^^^^  ^^^^^^ 
{ 

} 

そしてInternalExternal

アップデートでプライベートなので、この機能friendを宣言してください:あなたは友人を宣言する方法 がここにあります。あなたのクラス定義の書き込みで:友人-宣言が宣言ですので

template<class T, class Y> 
friend std::ostream& operator <<(std::ostream& out, const External::Internal<T,Y>&) 

、これはあなたの前方宣言の問題を解決します。

更新:循環依存関係を解決するために:

まずinternal

template<class T, class Y> 
class Internal; 

を前進宣言し、その後友人を宣言します。

あなたのクラスの残りの部分は動作するはずです。

+0

@Armenあなたが示唆したように私はそれを持っていますが、問題はむしろこの演算子の前方宣言にあります。 – smallB

+0

@small B:どういう意味ですか?それを友達に宣言する方法は? –

+1

@smallB:どのようなフォワード宣言ですか?コードには表示されません。 – ildjarn

0
template<class T, class Y> 
std::ostream& operator<<(std::ostream& out, const External::Internal<T, Y>&) 
{ 
} 

External::は、名前空間として振る舞い、operator<<定義は、クラス外部の外にあるので必要です。

1

Armenの回答は、<<オペレータ自身のために働くでしょう。

しかし、あなたのメンバ宣言

Internal data_; 

は同じように、また間違っています。つまり、Internalのテンプレート引数が欠けています。したがって、オペレータ実装の修正に加えて、メンバー宣言も修正してください。

最後に、C++ではすでに宣言されていない限り使用できないことに注意してください。インライン実装の<<の使用がprintに違反しています。だから、使用されているものが既に宣言されているように、物事を並べ替える(または宣言する)方がよいでしょう。

乾杯&hth。、

+0

+1、それはチェスをするときはいつも私の問題です - 私はボード全体ではなくボードの一部に集中します:) –

+0

Armenの答えはうまくいかないでしょう。 operator <<とExternal :: Internalの間には循環依存があります。問題は、宣言される前にこのoperator <<をExternalで使用することができず、不完全な型を使用する必要があるため宣言できないことです。 – smallB

+0

@smallB:おそらく、MSVCの古いバージョンのコンパイラのバグを実行している可能性があります(または、最新のものはチェックしていません)。ここで少なくとも2つの答えで適切な前方宣言が与えられているようです。 –

1

ポイントは前方宣言を使用している:

// you promise there will be implementation of this stuff later on: 
template<typename T, typename Y> 
class External::Internal<T, Y>; 

template<typename T, typename Y> 
std::ostream& operator<<(std::ostream& out, const External::Internal<T, Y>&); 

// now declare your class and operator<< function as normal 
class External 
{ 
    template<class T, class Y> 
    class Internal 
    { 
    }; 

    Internal<Foo, Bar> data_; 

    void print() 
    { 
     // here you can use operator<< with Internal 
     out << data_; 
    } 
}; 

template<class T, class Y> 
std::ostream& operator<<(std::ostream& out,const External::Internal<T, Y>&) 
{ 
} 
+0

あなたはそれをコンパイルしようとしましたか?それを試してみてください。 – smallB

+0

右。 「内部」は私的で、私はそれを認識しませんでした。その場合には、他者に示唆されているように、おそらく 'friend'関数を宣言するのがよいでしょう。 – Fiktik

0

を問題がありますこのオペレータコールを外部から使用しようとすると、

クラス定義内に手続き型コードを記述しないでください。宣言のみ。順番に

書き込み、:[ヘッダー内]

  • クラス定義[ソース・ファイルにこれらの事を使用しています
  • コード[ヘッダー内]
  • operator<<