2011-08-12 6 views
4

次のweak_ptrのコンストラクタの2のとおりです。(memoryから) http://msdn.microsoft.com/en-us/library/bb982126.aspxのweak_ptrの奇妙なコピーコンストラクタ

weak_ptr(const weak_ptr&); 

template<class Other> 
weak_ptr(const weak_ptr<Other>&); 

実際のコード:

weak_ptr(const weak_ptr& _Other) 
{ // construct weak_ptr object for resource pointed to by _Other 
    this->_Resetw(_Other); 
} 

template<class _Ty2> 
weak_ptr(const weak_ptr<_Ty2>& _Other, 
     typename enable_if<is_convertible<_Ty2 *, _Ty *>::value, 
     void *>::type * = 0) 
{ // construct weak_ptr object for resource pointed to by _Other 
    this->_Resetw(_Other); 
} 

Q1:なぜトップコピーコンストラクタでもあるのでしょうか?一番下のケースを含めて、下のケースがすべてのケースを説明するように見えます。それも呼び出されるのですか?もし彼らがそれを含んでいなければ、下の人がそれを取るでしょうか?

質問2:ボトム(テンプレート)コンストラクタの2番目の引数はどうなっていますか?私はSFINAEの側面を理解していると思うが、余分なものがある理由を理解していない::type

+0

@Hans、なぜインデントを修正しませんか? – Motti

答えて

5

Q1)コピーコンストラクタを記述しないと、コンパイラによって生成されないあなたが望むものになります。テンプレート変換コンストラクタはカウントされません。

Q2)T*のように、shared_ptr<T>は、ポインタのレベルで互換性をチェックする必要があります。 T*U*に変換可能な場合は、一方を他方に割り当てることができます。ポインターとベースを考えてみましょう。 [申し訳ありませんが、あなたが尋ねたものではありませんでした]最終的な引数型は存在する必要がありますが、引数自体を指定する必要もありません。デフォルトの引数を与えることができる型を作る普遍的な方法は、ポインタです。要するに、関数は存在するかもしれないし、存在しないかもしれない型に依存するようにする必要がありますが、実際にユーザーがこれを知る必要はありません。

+1

もし '*'が '= 0'の前になければ、それはまだ成功すればvoid *型になります。余分な*それを空にしていない**、なぜ彼らはvoid *の代わりにvoid **を書くのではないでしょうか? また、なぜ0の代わりにnullptrを書かなかったのですか?それは間違いですか? – David

+1

@Dave:あなたは* nullptrを使う必要はありません。これはオプションの新機能です。とにかく、なぜ実際にダブルポインタが必要なのか分かりません。ポインタを介して常にSFINAEを使用するのはハウススタイルなのでしょうか?この場合、インナータイプに 'void * 'を使用しただけです。 GCCは関数の引数でこれを行うのではなく、代わりに既定のテンプレート引数を使用して、ランタイムコストゼロの置換失敗をトリガします。 –

+2

LOL。私はちょうど_Ptr_Baseに基づくweak_ptrのようなものを書いていました。もし、その2番目の '*'が話しているのであれば、VSは... 'エラーエラーC1001:コンパイラで内部エラーが発生しました。 だからこそそこにいるのです。 HA。 – David

3

Re Q1:テンプレート化されたコンストラクタは、コピーを管理していても決して "コピーコンストラクタ"ではありません。ユーザ定義の "コピーコンストラクタ"がない場合、コンパイラは必要に応じてコンパイラを生成します。

Re Q2:2番目の引数、デフォルトで0に設定されたポインタは、enable_ifを配置する場所です。 Boostのドキュメントでそのことについてもっと知ることができます。

乾杯& HTH。、