2009-06-07 27 views
5

最近、演算子のオーバーロード/テンプレートの能力を測定しようとしていましたが、小さなテストとして、以下のコンテナクラスが作成されました。このコードはうまくコンパイルされ、MSVC 2008(ディスプレイ11)の下で正しく動作しますが、MinGW/GCCとComeauの両方がoperator+オーバーロードで窒息します。私がMSVC以上に信頼しているので、私が間違っていることを理解しようとしています。それはどこですので、テンプレートクラスのバイナリ演算子オーバーロード

Comeau C/C++ 4.3.10.1 (Oct 6 2008 11:28:09) for ONLINE_EVALUATION_BETA2 
Copyright 1988-2008 Comeau Computing. All rights reserved. 
MODE:strict errors C++ C++0x_extensions 

"ComeauTest.c", line 27: error: an explicit template argument list is not allowed 
      on this declaration 
    Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
      ^

1 error detected in the compilation of "ComeauTest.c". 

私はコモ/ MingGWがボールをプレイするために取得しようと苦労している:

#include <iostream> 

using namespace std; 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
    public: void setobj(T ob); 
    T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
    obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
    return obj; 
} 

template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

a.setobj(5); 
    b.setobj(6); 

Container<int> c = a + b; 

cout << c.getobj() << endl; 

    return 0; 
} 

これは、コモが与えるエラーは次のとおりです。ここで

コードです私はあなたたちに目を向ける。私の脳はC++構文の重さの下でこれが大きく溶けてしまったので、長い時間がかかりました。だから私はちょっと恥ずかしいです。

EDIT:初期のComeauダンプにリストされている(無関係な)左辺値の誤差を排除しました。

答えて

5

私は解答を見つけましたto this forum posting。基本的には、クラス内で 'friend'を使用する前に関数プロトタイプを用意する必要がありますが、関数プロトタイプを適切に定義するには、クラスを宣言する必要もあります。したがって、解決策は、上部に関数とクラスの2つのプロトタイプ定義を持たせることです。次のコードは、3つのすべてのコンパイラの下でコンパイルされます。あなただけの一般的なものを専門にない、新しいテンプレートを宣言しているので、operator+後にここで

#include <iostream> 

using namespace std; 

//added lines below 
template<typename T> class Container; 
template<typename T> Container<T> operator+ (Container<T>& lhs, Container<T>& rhs); 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
     public: void setobj(T ob); 
       T getobj(); 
     private: T obj; 
}; 

template <typename T> 
void Container<T>::setobj(T ob) 
{ 
     obj = ob; 
} 

template <typename T> 
T Container<T>::getobj() 
{ 
     return obj; 
} 

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
{ 
     Container<T> temp; 
     temp.obj = lhs.obj + rhs.obj; 
     return temp; 
} 

int main() 
{  
    Container<int> a, b; 

    a.setobj(5); 
    b.setobj(6); 

    Container<int> c = a + b; 

    cout << c.getobj() << endl; 

    return 0; 
} 
2
template <typename T> 
Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs) 

は「<>」削除する必要があります。また、少なくともg++は、友人宣言の前にテンプレート宣言を見たいので、宣言の前に移動する必要があります。Container。したがって、宣言の次の順序は機能します。

// forward declaration of Container<T> 
template <typename T> 
class Container; 

template <typename T> 
Container<T> operator+(Container<T>& lhs, Container<T>& rhs) 
{ ... } 

template <typename T> 
class Container 
{ 
     friend Container<T> operator+ <> (Container<T>& lhs, Container<T>& rhs); 
     ... 
}; 
0

'演算子+'はメンバー関数ではなく、テンプレート化されていません。それはテンプレート化されたパラメータを取る演算子+です。

template <typename T> 
Container<T> operator+ (Container<T>& lhs, Container<T>& rhs) 
+1

私はオペレータ+がテンプレート化された関数だと思いますか? コンテナとコンテナは2つの異なるタイプなので、コンパイラは2つの異なる演算子+関数を生成する必要があります。それは演算子+がテンプレート化された関数であることを意味しないのですか? –

+0

*は*関数テンプレートです。しかし、あなたはテンプレートの定義から "<>"を省略することに間違いはありません。 ( "<>"は、*を呼び出すために関数テンプレート*を指定する場合にのみ使用され、同じ名前のテンプレート以外の関数が存在する場合にのみ必要です) –

1

私はこれをGCCで撮影し、いくつかの変更を加えてコンパイルして実行しました。私はGCCを幸せにするために2つの変更が必要でした。

1つは、フレンドテンプレート関数の宣言でした。クラス1とは別の独自のテンプレート宣言なので、Containerクラスの代わりにUを使用しました。私はまた、演算子+の後に<を取り除いています。私はあなたがテンプレートの専門化を書いていない限り、あなたがそれらを必要とするとは思わない。

 template<typename U> 
     friend Container<U> operator+ (Container<U>& lhs, Container<U>& rhs); 

つあなたが(加算結果)一時的に参照を格納するために求めているので、

ラインは、GCCで飛びませんでした。アンパサンドを削除して、結果を保存する場所があるようにしました。

私はあなたの投稿を見ましたが、これは前方宣言のためにも機能します。私は、とにかくこれを必要としない代替手段として掲示すると思う。もちろん私はGCCでのみテストしました...

+0

これは別のポスティングオンラインでこれが見つかりました。 2人の個人的な好み(より簡潔)。 – GRB

+0

これはすべてのテンプレート特殊化へのアクセスを許可します(operator + はContainer の秘密にアクセスできます)。質問者のコードは、オペレータ+ へのアクセスのみを許可したいと考えています(コンテナのオペレータ+ のみがにアクセスできます) –

+0

@litb:この問題も同様ですが、このようなシナリオの設定には問題があります。 int overloadがfloatのプライベートメンバーにアクセスするサンプルコードスニペットを提供できますか? – GRB

1

クラス内で直接関数を定義する方がよいでしょう。また、パラメータをconstの参照として渡す必要があります。

template <typename T> 
class Container 
{ 
public: 
    friend Container operator+ (Container const & lhs, Container const & rhs) 
    { 
     // ... 
    } 
}; 
関連する問題