2009-04-03 5 views
0

std :: setのカスタムオブジェクトを返す(C++)メソッドを記述したいと思います。私はしかし、オブジェクトを挿入するときに使用されるコンパレータを公開したいので、私はそれをプライベートクラスにします。 (返却時に暗黙的に)プライベートコンパレータでstd :: setを返すには

std::set<some_class, some_class_comparator> return_object; 

は今、私はセットを返すようにしたいので、それは次のようにキャストする必要があります: は、私はこのようなセットを作成

(const std::set<some_class>) return_object; 

これは、コンパイラが文句れる場合。コンパイラを使用して不変のセットに変更可能なセットをキャストする方法はありますか?

おかげでたくさん、私はそうは思わない

ホルガー

+0

コンパレータなしでリターンセットが必要な理由を説明してください。あなたが帰ってから何を使うのか。 – bayda

+0

また、「プライベートクラス」とはどういう意味ですか? –

+0

私にとって、プライベートクラスは潜在的なユーザーが決して見ることのできないクラスです。これは彼がそれを説明するヘッダを決して得られないことを意味する。 –

答えて

1

。 AFAIK std::set<some_class>std::set<some_class, std::less<some_class> >の省略形にすぎません。そのため、このセットは必要に応じて変換できません。

コンパレータを必要とせずに現在のアイテムを順序どおりに保持する他のデータ構造(たとえばベクトル)にアイテムを転送することをお勧めします。

+0

残念ながら、私は戻り型のセマンティックな意味を失うでしょう - 私は彼がコレクション内のユニークなアイテムを期待できることをユーザーに伝えて欲しいです。 –

+0

@hp:セットは一意性以上の表現です。不変のものでさえ、対数の複雑さを伴うfind()を実行するためにコンパレータが必要です。そのため、比較器は型の本質的な部分であり、 "キャスト・アウト"することができません。 –

+0

@エリック:うん、そうです。 STLで:-)。一般的に(a.k.a.数学)集合はユニークでなければならない。期間 - 私は集合が最初に順序を持つべきであることが奇妙であることを知る。パフォーマンス上の理由からであり、可能な限りユーザーから隠されている必要があります。 –

4

せず不変 にコンパレータで変更可能なセット をキャストする方法はありますか?

ませんので

std::set<some_class, some_class_comparator> 

std::set<some_class> 

全く異なる、無関係なタイプです。テンプレートは単なるテンプレートです。テンプレートは、コンパイル前に型を生成する方法を指定する方法です。後者の場合、コンパレータはstd :: setに付属するデフォルトの比較器です。

some_class_comparotorがプライベートである必要があるという説得力のある理由はありますか?それはそれ自身の独立した実体でしょうか?クラスのパブリックインターフェイスを汚染したくないだけですか?

+0

右ですが、キャスト演算子を使用して直感的に共変な型に生成(実装)することができます –

+0

実際には共変ではありません。 – MSalters

0

std :: <タイプ、Comparator>、およびstd :: set <タイプ、DefaultComparator>です。

0

仮想ファンクションのように聞こえる、テンプレートのようには聞こえない実装の詳細を呼び出し元から隠したいとします。私はまず、あなた自身に尋ねる必要があると思います。これは本当に重要ですか?その場合は、クラスをIOpaqueSetインターフェイスの背後に隠します。もちろん、他のSTL操作では動作しません。

+0

IOpaqueSetがイテレータを実装する限り、すべてのSTL操作がイテレータで機能します。 Cf。 std :: setそれ自体は、通常、赤黒のツリーの不透明なラッパーです。 RBツリーを反復することはできませんが、セット全体を繰り返し処理することはできます。 – MSalters

1

あなたの最善の解決策は、このようなものです:

class MyClass 
{ 
    class some_class_comparator; 
public: 
    typedef std::set<int, some_class_comparator> ReturnSet; 
    ReturnSet myMethod(); 
    // ... 
private: 
    class some_class_comparator 
    { 
    public: 
     bool operator< (MyClass& m) {return true;} 
    }; 
}; 

//later... 
MyClass::ReturnSet s = my_class_instance.myMethod(); 
+0

これはできますか?デストラクタを公開する必要がありますか?私はあなたが言うように、これを行うことができると思う - 私はちょうどそれが働くことを確かに知らない。 –

+0

それは動作します。もちろん、これを回避するには、MyClass :: ReturnSet :: key_compareを使用します。しかし、プログラマがあなたのカプセル化を巧妙にすることを望むなら、彼は一般的に可能です。 – rlbond

0

STLは、組み込みクラスの多くが付属していますが、それはまた、拡張可能なフレームワークです。イテレータを定義して:: own :: immutable_setを定義すると、他のSTLアルゴリズムでも使用できます。 immutable_set<T>は、可変のstd::set<T, comparator<T> >のまわりの薄いconstラッパーとして定義されます(異なるコンパイラーをサポートするためにはいくつかのテンプレートマジックが必要です)。 immutable_set<T>::iterator::operator++std::set<T>::iterator::operator++などに転送されます。

関連する問題