2012-06-21 18 views
6

関数の戻り値の型にワイルドカード型(?)が無制限であるJavaコードがあります。 C++でこれをどのようにエミュレートできますか?例えばJavaでC++に「疑問符(?)」ジェネリック型をエミュレートするにはどうすればよいですか?

public GroupHandlerSetting<?> handleGroupProcessingFor(final EventHandler<T> eventHandler) 
    { 
     return new GroupHandlerSetting<T>(eventHandler, eventProcessors); 
    } 
+4

また、C++テンプレートはJava Genericsと少し似ていません。 C++テンプレートは新しい型を作成します。 Java Genericsは既存の型を制限します。 C++のテンプレートは、基本的にグラフト・オン・タイプのルールを持つ前処理です。 Java Genericsは型理論に基づいて構築されています。表記法に似ていると考えることに惑わされないでください。彼らはそうではありません。 – EJP

+3

Joshua Bloch氏は、さまざまなビデオで、戻り値の型にワイルドカードを使用しないことを述べています。彼らはあなたのケースでは良いアイデアだと確信していますか?あなたはその機能または少なくともその署名を投稿できますか? – fredoverflow

+0

お願いします、機能を追加できますか? –

答えて

6

C++では、使用するかどうかにかかわらず、すべての型引数には名前を付ける必要があります。疑問符はありません。関数のテンプレート引数にして、名前を付けて、あなたはうまくいくはずです。

些細な部分です
template <typename T> 
struct templ { 
    template <typename U> 
    void assign(templ<U> & u);  // public void assign<?>(temple<U> u)  
}; 

、より複雑な部分は、型の制約を強制され、そのためにあなたはSFINAEを使用することができます。

で、SFINAEためのC++ 11を使用している
template <typename T> 
struct templ { 
    template <typename U, typename _ = std::enable_if< 
           typename std::is_base_of<U,T>::value 
             >::type > 
    void super(templ<U> & u);  // public void super_<? super T>(templ<?> u) 

    template <typename U, typename _ = std::enable_if< 
           typename std::is_base_of<T,U>::value 
             >::type > 
    void extends(templ<U> & u);  // public void extends_<? extends T>(templ<?> u) 
} 

C++ 03では、関数テンプレート引数でSFINAEを使用できないので、(このバージョンが単純だったかのように)ちょっと畳み込まれているので、SFINAEを戻り値の型または余分な関数の引数のいずれかに適用する必要があります。 SFINAEははるかに強力なソリューションであり、superextendsを提供するだけでなく、多くの他の種類の機能やコンパイル時の値を提供するために使用できます。 SFINAEのためのGoogleとあなたはSFINAEが使用されている多くのケースを見つけるでしょう、それらの多くはC + + 03スタイルになります。

構文が大幅に簡略化されるが、合意に達することはなかった概念が提案され、標準を完了まで移して後の標準で延期した。

これはC++ではJavaほど一般的ではないので、あなたは何をしたいのかという別の質問をすることをお勧めします。より慣用的なC++でデザインのアイデアを得ることができます。

+2

これは全く同じことではありません。コールサイトでこれらの2つを比較してください:http://ideone.com/2LXUpとhttp://ideone.com/bMMJr。ワイルドカードをエミュレートする場合は、「消去」と入力する必要があります。 –

+0

@ R.MartinhoFernandes:テンプレートとジェネリックは同じものではありませんが、テンプレートを使用してジェネリックで実行できるすべてのジェネリックコードを実装できます。あなたの例では、C++はその特定の*コード臭をサポートしていません*、Javaの専門家はreturn文で '?'を使用しないことをお勧めしますので、メソッドの実装は型を知っているので*それを公表しない理由。戻り値の型で '? 'が提供する唯一の利点は、呼び出し先がプレースホルダに対して別の型を返す場合に呼び出し元を再コンパイルする必要がないということです。 –

+0

...これはC++では効果的にテンプレートとして使用できません。バイナリ互換性(そして、コールサイトで不自然なタイプを使用することができます - あなたにはいくつかの小さな機能がありますが、実質的にあなたに知られていないタイプ)は機能ではありません。あなたの例では、Javaのバージョンでは、常に 'ArrayList 'を返しています。したがって、C++の同等の例は、非標準的な関数 'std :: vector getSomeList()'です。質問では、このメソッドはジェネリッククラス( 'T'からの推測)の一部であり、テンプレートのテンプレート化されていないメンバ関数です。 –

1

具体的な例は簡単です。私はJavaを使用していないので、そこに<?>が必要な理由を理解できません。

template<class T> 
GroupHandlerSetting<T> handleGroupProcessingFor(EventHandler<T> const& evHandler){ 
    return GroupHandlerSetting<T>(evHandler, evProcessors); 
} 

ThandleGroupProcessingForに渡されるどんな引数から推論されます、我々はあなたが行う基本的にはまさに、戻り値の型のためにちょうど同じTを使用:C++では、あなただけの同じテンプレートパラメータに記入します関数の本体。

+0

私はこれについてはわかりません。もし私が単にに置き換えることができたら、私はそれもJavaで行うことができると思います。なぜが必要なのか分かりません。私はJavaの知識がほとんどないので間違っているかもしれません。 – polapts

+1

@polapts:Davidの答えに対するコメントを読むと、タイプ消去には ''が必要です。あなたの特定の例では、単純な議論の控除で逃げることができます。 – Xeo

+0

@Xeo: '?'はタイププレースホルダです。基本的に別のタイプの引数で、名前を付けても気にしません。 *未知*型が何であるかにいくつかの制約を置くことができます。つまり、それを基底にするか、別の型(汎用引数か固定型か)から派生させることができます。あなたのコードと質問コードとの違いは、あなたのコードでは、 'T'型は引数とreturn文の両方で同じになりますが、質問のコードではそうではありません(内部的に' GroupHandlerSetting 'とは関係なく' T'とコンパイルしてしまいます。 –

関連する問題