この場合、gcc 4.6 の標準ライブラリ ヘッダーは間違っているようです。標準では次のコンストラクタが必要なためです (§20.7.2.2.1/16)。
shared_ptr(const shared_ptr& r) noexcept;
これは、gcc 実装に欠けていると思われるコピー コンストラクターです。私が手元に持っている実装(g++-4.6.0)は(で)提供していますbits/shared_ptr.h
:
template<typename _Tp1>
shared_ptr(const shared_ptr<_Tp1>& __r)
ただし、適切なコピー コンストラクターがありません (テンプレート化されたコンストラクターは、コンパイラーによってコピー コンストラクターとして使用できません)。しかし、そのようなエラーが本番コンパイラで発生するのは奇妙だと思います...
編集私は、g ++ 4.6が上記のコードを独自の標準ライブラリでコンパイルする理由を理解しようとしています。コピー構築の実行可能なオーバーロードとして d コンストラクターを取り上げているようでtemplate
、これがバグかどうかを確認するために標準を振り返りました。コピー コンストラクタかどうか。
C++03 標準では、脚注があります106) 。
テンプレート コンストラクターは決してコピー コンストラクターではないため、そのようなテンプレートが存在しても、コピー コンストラクターの暗黙の宣言は抑制されません。テンプレート コンストラクターは、コピー コンストラクターを含む他のコンストラクターとのオーバーロードの解決に参加します。テンプレート コンストラクターは、他のコンストラクターよりも適切に一致する場合、オブジェクトをコピーするために使用できます。
その脚注は C++11 にはありません。脚注は規範的ではないため、その脚注を裏付ける別の引用が必要です。その下にいくつかの段落があります。
12.8/3 クラス X のコンストラクターの宣言は、その最初のパラメーターが X 型 (オプションで cv 修飾されている) であり、他のパラメーターがないか、他のすべてのパラメーターに既定の引数がある場合、形式が正しくありません。メンバー関数テンプレートは、クラス オブジェクトをそのクラス型のオブジェクトにコピーするためにインスタンス化されることはありません。
段落の最初の部分は、コンストラクターが引数と同じ型を取ることができないことを意味します (コピー コンストラクターは参照を受け取り、そのようなコンストラクターを許可するとあいまいさが生じます。また、引数へのコピーが必要になるため、最適なオーバーロードが必要になるという事実もあります)。 --これがコピーコンストラクターを抑制したと仮定すると--同じ関数になり、それには...無限ループが必要になります)。
条項の 2 番目の部分では、テンプレート化されたコンストラクターを使用して型のコピーを作成することはできないと述べています。これは、脚注106)をサポートする規範的なセクションのようです。現在、これは C++11 で慎重に書き直され、次のように述べられています。
12.8/6 クラス X のコンストラクターの宣言は、その最初のパラメーターが X 型 (オプションで cv 修飾) であり、他のパラメーターがないか、他のすべてのパラメーターにデフォルト引数がある場合、形式が正しくありません。メンバー関数テンプレートは、そのようなコンストラクター シグネチャを生成するためにインスタンス化されることはありません。
さて、これが意味することは、テンプレートを使用してコピーできないという制限が削除され、より厳密でない制限に置き換えられたことです: テンプレートはフォームのコンストラクターを生成するためにインスタンス化されませんS( S )
。コピー コンストラクター。
このより少ない制限により、上記のテンプレート化されたコンストラクターは、生成される署名に互換性があるため、実際にはcopy-constructorとして使用できるようです。bits/shared_ptr.h
これは、ヘッダーを処理するときの g++ 4.6 コンパイラの動作をサポートしておりclang++
、テンプレートを有効なコンストラクタとして使用できていないことを意味します。
次の問題は、g++4.6 に同梱されている標準ライブラリの実装が実際に準拠しているかどうかです。私は頭の上から言うことはできません。一方では、前述のコンストラクターの署名が欠落しているため、準拠していないと主張できます。しかし一方で、準拠したコンパイラは、同じ機能を実現するためにテンプレート化されたコンストラクターを取得する必要があり、実装はそのコンストラクターが存在するかのように動作します。