web-dev-qa-db-ja.com

C ++の内部typedef-良いスタイルか悪いスタイルか?

私が最近頻繁にやっていることを見つけたのは、そのクラス内の特定のクラスに関連するtypedefを宣言することです。

class Lorem
{
    typedef boost::shared_ptr<Lorem> ptr;
    typedef std::vector<Lorem::ptr>  vector;

//
// ...
//
};

これらのタイプは、コードの他の場所で使用されます。

Lorem::vector lorems;
Lorem::ptr    lorem( new Lorem() );

lorems.Push_back( lorem );

好きな理由:

  • クラステンプレートによって導入されるノイズを減らし、std::vector<Lorem>Lorem::vectorになります。
  • これは意図のステートメントとして機能します。上記の例では、Loremクラスはboost::shared_ptrを介して参照カウントされ、ベクトルに格納されることを意図しています。
  • 実装を変更できます-つまり、後の段階で(boost::intrusive_ptrを介して)侵入参照参照するためにLoremを変更する必要がある場合、コードへの影響は最小限になります。
  • 見た目は「きれい」で、間違いなく読みやすいと思います。

気に入らない理由:

  • 依存関係に問題がある場合があります-たとえば、別のクラスにLorem::vectorを埋め込みたいが、(ヘッダーファイルに依存関係を導入するのではなく)Loremを前方宣言する必要がある(またはしたい)場合は終了します明示的な型(例:boost::shared_ptr<Lorem>ではなくLorem::ptr)を使用する必要がありますが、これは少し矛盾しています。
  • あまり一般的ではないので、理解するのは難しいですか?

私は自分のコーディングスタイルを客観的にしようとしています。そのため、他の意見を聞いて、自分の考えを少し分析してみてください。

167
Will Baker

私はそれが素晴らしいスタイルだと思います、そして私はそれを自分で使います。名前の範囲をできる限り制限することが常に最善であり、C++でこれを行うにはクラスの使用が最善の方法です。たとえば、C++標準ライブラリは、クラス内でtypedefを多用します。

142
anon

これは、意図のステートメントとして機能します。上記の例では、Loremクラスは、boost :: shared_ptrを介して参照カウントされ、ベクトルに格納されることを意図しています。

これはまさにnot doです。

コードに「Foo :: Ptr」と表示されている場合、それがshared_ptrかFoo *(STLにはT *である:: pointer typedefがあります)かどうかはまったくわかりません。 Esp。共有ポインタの場合、typedefをまったく提供しませんが、コードでshared_ptrの使用を明示的に保持します。

実際、テンプレートメタプログラミング以外でtypedefを使用することはほとんどありません。

STLは常にこのタイプのことを行います

メンバー関数とネストされたtypedefの観点で定義された概念を持つSTLデザインは歴史的な袋小路であり、現代のテンプレートライブラリは組み込み関数を除外しないため、無料の関数と特性クラス(Boost.Graphを参照)を使用しますコンセプトをモデル化することにより、与えられたテンプレートライブラリのコンセプトを念頭に置いて設計されていない型をより簡単に適合させることができます。

同じ間違いをする理由としてSTLを使用しないでください。

13

Typedefは、C++で ポリシーベースの設計と特性 に基づいているものであるため、C++の汎用プログラミングの力はtypedef自体に由来します。

9
Özgür

Typdefsは間違いなく良いスタイルです。そして、あなたの「私が好きな理由」はすべて良くて正しいです。

それに関してあなたが持っている問題について。まあ、前方宣言は聖杯ではありません。コードを設計するだけで、マルチレベルの依存関係を回避できます。

Typedefをクラスの外に移動できますが、Class :: ptrはClassPtrよりもずっときれいなので、私はこれを行いません。私にとって名前空間のようなものです-物事はスコープ内で接続されたままです。

たまにやった

Trait<Loren>::ptr
Trait<Loren>::collection
Trait<Loren>::map

また、すべてのドメインクラスのデフォルトで、特定のクラスに特化したものにすることができます。

8
Mykola Golubyev

これに対するもう一つの投票は良い考えです。時間と空間の両方で効率的でなければならないシミュレーションを書くときに、これを始めました。すべての値タイプには、ブースト共有ポインターとして開始されたPtr typedefがありました。その後、いくつかのプロファイリングを行い、これらのオブジェクトが使用されているコードを変更することなく、それらの一部をブースト侵入型ポインターに変更しました。

これは、クラスが使用される場所がわかっている場合にのみ機能し、すべての使用には同じ要件があることに注意してください。たとえば、ライブラリを記述するときに、それが使用されるコンテキストを知ることができないため、ライブラリコードではこれを使用しません。

3
KeithB

STLは常にこのタイプのことを行います-typedefはSTLの多くのクラスのインターフェイスの一部です。

reference
iterator
size_type
value_type
etc...

さまざまなSTLテンプレートクラスのインターフェイスの一部であるすべてのtypedefです。

3
Michael Burr

現在、これらの種類のtypedefを集中的に使用するコードに取り組んでいます。これまでのところそれは結構です。

しかし、繰り返しtypedefが非常に頻繁にあり、定義がいくつかのクラスに分割されており、どのタイプを扱っているかを実際に知ることはありません。私の仕事は、これらのtypedefの背後に隠されているいくつかの複雑なデータ構造のサイズを要約することです。したがって、既存のインターフェースに頼ることはできません。 3〜6レベルのネストされた名前空間と組み合わせて使用​​すると、混乱が生じます。

したがって、それらを使用する前に、考慮すべき点がいくつかあります

  • 他の誰かがこれらのtypedefを必要としますか?クラスは他のクラスで多く使用されていますか?
  • 使用を短くするか、クラスを非表示にしますか? (非表示の場合は、インターフェイスも考えられます。)
  • 他の人がコードを使用していますか?どうやってやっているの?彼らはそれが簡単だと思いますか、それとも混乱しますか?
2
Bodo

これらのtypedefをクラス外に移動することをお勧めします。この方法では、共有ポインターおよびベクトルクラスへの直接の依存関係を削除し、必要な場合にのみそれらを含めることができます。クラス実装でこれらの型を使用している場合を除き、これらの型は内部typedefであってはならないと考えています。

好きな理由は、クラス内で宣言するのではなく、typedefを介した型エイリアスによって解決されるため、依然として一致しています。

1

Typedefがクラス自体内でのみ使用されている場合(つまり、プライベートとして宣言されている場合)、それは良い考えだと思います。ただし、正確にあなたが指定した理由のために、typedefをクラス外で知る必要がある場合は使用しません。その場合、クラスの外に移動することをお勧めします。

0