Boost :: shared_ptrテンプレートをtypedefするための命名規則をめくっています。例えば:
typedef boost::shared_ptr<Foo> FooPtr;
慣習を決める前に、他の人が何を使用しているかを確認したいと思います。あなたの慣習は何ですか?
編集:
Fooの内部でtypedefをネストしている人にとって、Fooがどのように渡されるかを "認識"していることは気になりませんか?それはカプセル化を壊すようです。これはどう:
class Foo
{
public:
typedef std::vector<Foo> Vector
};
あなたは今これをしませんか? :-)
物議をかもすかもしれませんが、この古い質問にもいくつかオプションを追加したいと思います…
OldPeculier's answer に似ています。私は、標準のポインタにできるだけ似た短い型名が好きです。
ほぼどこでもshared_pointer
を使用するプロジェクトでは、
typedef boost::shared_ptr<Foo> Foo_;
// usage examples:
Foo* myFoo0;
Foo_ myFoo1;
私は3つのことを利用しました。
Foo* myFoo1;
よりFoo *myFoo1;
を好んでおり、Foo_ myFoo2
とうまく一致しています。さまざまな種類のスマートポインターのtypedefが必要な場合は、
typedef shared_ptr<Foo> Foo_S;
typedef weak_ptr<Foo> Foo_W;
typedef unique_ptr<Foo> Foo_U;
// usage examples:
Foo* myFoo2;
Foo_S myFoo3;
Foo_W myFoo4;
Foo_U myFoo5;
標準とコンパイラの実装におけるUnicodeサポートの増加に伴い、これらのスター文字が型識別子の通常の部分として扱われると想定して、次の構文を試してみたくなります。もちろん、これは関係するすべての開発者がこれに便利なテキスト入力方法を持っている場合にのみ実用的です。
typedef shared_ptr<Foo> Foo★;
typedef weak_ptr<Foo> Foo☆;
typedef unique_ptr<Foo> Foo✪;
// usage examples:
Foo* myFoo6;
Foo★ myFoo7;
Foo☆ myFoo8;
Foo✪ myFoo9;
(簡単なテストでは、少なくとも私のビルド環境では、これが実際に機能しないことが示されました。ただし、Foo_ä
の場合も同様です。)
回答:それをしないでください。それはあなたと他の誰にとっても便利です。どういう意味かお話しください。
私の好み:
class Foo
{
public:
typedef boost::shared_ptr<Foo> SharedPointer;
};
FooPtr
だけの問題は、ポインタのタイプが異なる可能性があることです(例:weak_ptr
s)。私は略語もあまり気にしませんが、それはまったく別の問題です。
個人的に、私が担当するコードでは、通常、Fooと同じ名前空間スコープでFooPtr typedefが表示されますおよびFooにはFooPtrと同じタイプへの総称的な「SmartPtr」typedef。 FooPtrを使用すると、冗長でない手動での使用が簡単になります。 「SmartPtr」またはいくつかの同等の入れ子のtypedefがあると、スマートポインターの実際の型を知らなくても、テンプレートやマクロなどで簡単に汎用的に使用できます。
また、この質問に「主語」タグを追加することをお勧めします。
私は外側とカプセル化されたtypedefの両方を使用しましたが、最終的には最初の
typedef boost::shared_ptr<Foo> FooPtr;
結合された式では、これはFoo::Ptr
よりもきれいに見えるからです。
Fooがどのように渡されるかを "認識"していることを気にしませんか?
多くの場合、これらのクラスはファクトリメソッドを通じてのみ作成できます。
struct Foo
{
static FooPtr Create() { return FooPtr(new Foo); }
protected:
Foo() {}
}
これは、typedefをカプセル化するよりも「強力」ですが、非常に一般的なパターンです。
通常、typedef
をクラス内にカプセル化します。その理由は、メモリに敏感なコードがあり、それによって boost::shared_ptr
および boost::intrusive_ptr
以降 intrusive_ptr
はクラスがサポートする必要があるものであり、どの共有ポインタを使用するかをクラスにまとめるのは私にとって理にかなっています。
私はハンガリーの命名規則の大ファンではありません、私は通常使用します:
typedef boost::shared_ptr<Foo> FooSharedPtr;
明確にするために十分に詳細ですが、巨大な面倒にならないように十分に短いです。いずれにせよ、特にそのポインタを将来使用するのはあなただけではない場合は特に、それが共有ポインタであることを明確に示します。
私は一般的に非常に短い識別子のファンではありませんが、これはそれらを使用する1つのケースです。
class Foo
{
public:
typedef std::shared_ptr<Foo> p;
};
これにより、shared_ptrは、混乱のリスクなしに、通常のポインターにできる限り似たものになります。
Foo* myFoo;
Foo::p myFoo;
また、カプセル化を解除することに関しては、いいえ、クラス内でshared_ptr型をtypedefingしても、クラスの外でカプセル化を解除するだけでカプセル化を解除しません。 「カプセル化」のどのような意味に違反しますか? Fooの実装については何も明らかにしていません。タイプを定義するだけです。これは、Foo *とFooの関係に完全に類似しています。 Foo *は、Fooへの特定の種類のポインタ(デフォルトの種類)です。 Foo :: pは、Fooへの別の種類のポインタです。カプセル化を壊すのではなく、型システムに追加するだけです。
typedef shared_ptr<Foo> sptr_Foo;
typedef weak_ptr<Foo> wptr_Foo;
typedef unique_ptr<Foo> uptr_Foo;
私の最初の応答は、「なぜtypedefなのか」と尋ねることです。
あなたの編集への返信:実際、それは多くの状況で役立つかもしれないかなり興味深いアプローチです。あなたが持っているかもしれないあなたの元の質問に戻るためにそれを使う:
struct object
{
typedef object* ptr_t;
typedef shared_ptr<object> shared_ptr_t;
typedef weak_ptr<object> weak_ptr_t;
typedef unique_ptr<object> unique_ptr_t;
etc...
}
タイプを短くする代わりに、名前空間を削除します。
using boost::shared_ptr; // or using std::shared_ptr,
struct Foo
{
shared_ptr<Foo> impl;
};
これには、実装間で簡単に変更できるボーナスがあります。
それでもまだ長すぎる場合(ちょうどいいと思います):
using boost::shared_ptr;
template<class T> using sptr = shared_ptr<T>;
struct Foo
{
sptr<Foo> impl;
};
_t
で終わるのはいいことです。
class Bar
{
public:
typedef boost::shared_ptr<Bar> Ptr_t;
};
どうですか:
template <typename T>
class Shared
{
public:
typedef std::shared_ptr<T> Ptr; // or boost::shared_ptr if you will
};
次に、次のように、Shared
クラスが独自のPtrオブジェクトを持つことを許可します。
class myClass : public Shared<myClass>
{
};
int main()
{
myClass::Ptr object;
//...
object->foo();
}
typedef boost::shared_ptr<MyClass> MyClass$;
これは私がフリップフロップした規則の1つでした。
typedef boost::shared_ptr<Foo> FooProxy;
...それを見てboost::shared_ptr
は Proxy パターンのアプリケーションです。
class foo;
typedef boost::shared_ptr<foo> foo_p;
typedef boost::weak_ptr<foo> foo_wp;