FCD (N3092) 20.9.11 に対する NB コメント (仮案)
1) 20.9.11
2) shared_ptr, weak_ptr は所有の共有に関する同値関係を反映した hash をサポートすべきである.
2つの shared_ptr オブジェクト p, q に対して, ポインタ値に関する同値関係 (式 p.get() == q.get() から導出される同値関係) と, 所有の共有に関する同値関係 (式 !p.owner_before(q) && !q.owner_before(p) から導出される同値関係) の 2つの同値関係を定義することができる.この同値関係は一般には独立な関係である. (20.9.11.2.1 パラグラフ 14 から 20.9.11.2.1 パラグラフ 18 で規定されている コンストラクタによって構築された shared_ptr が,この2つの関係が独立となる例である.) また,2つの weak_ptr オブジェクトに対しても同様に所有の共有に関する同値関係を定義することが出来る.
この2つの同値関係の各々に基づいてたとえば unordered associative container の key として shared_ptr を設定すること, あるいは所有の共有に関する同値関係に基づいて weak_ptr を unordered associative container の key として weak_ptr を設定することは,それぞれ極めて妥当な使用方法であると考えられる.
ところが shared_ptr に対する hash support は 20.9.11.6 においてポインタ値に関する同値関係を反映したものが規定されているのみであり, また weak_ptr に対する hash support はない.
shared_ptr, weak_ptr のオブジェクトが所有を共有しているかどうかに関する情報は 利用者からは取得できないものであり,所有の共有に関する同値関係を反映した hash を行う ユーザ定義の関数オブジェクト型を規定されているメンバ関数・自由関数から実装することは不可能である.
このような hash support は,特に weak_ptr を key とする unordered associative container を作成するという,意義の極めて大きい利用法を想定した場合に不可欠である. また,このような想定においては, weak_ptr に対して expired メンバ関数が true を返す状況でもこのような hash を実行することも必要となり, この場合には weak_ptr を shared_ptr に格上げしてから hash を行うといったことが不可能となるため, shared_ptr のみに所有の共有に関する同値関係を反映した hash をサポートすることも認められない.
以上の理由から shared_ptr, weak_ptr は所有の共有に関する同値関係を反映した hash をサポートすべきとコメントする.
3) 要求する修正
次の条件を満たす unary function object type H を仕様として規定すべきである.
「H のオブジェクト h に対して h(p) と h(q) は p と q が所有を共有している時に同じ std::size_t 型の値を返す. ただし, p, q は shared_ptr または weak_ptr のオブジェクトである.」
ただし shared_ptr については,たとえば p, q に対して get_deleter<D>(p) == get_deleter<D>(q) が p と q が所有を共有している場合に true を返すことを 20.9.11.2.11 で明確に規定するのであれば, get_deleter の戻り値を用いてユーザ側で hash support を実装することが出来るためこの限りではない.