C++1z owner_lessで任意の要素型を持つshared_ptr同士を比較できるようにする

所有権ベースの小なり比較を行うstd::owner_less関数オブジェクトですが、そのクラステンプレートのパラメータによってスマートポインタの要素型を制約してしまうため、以下のような比較ができませんでした。

shared_ptr<int> sp1;
shared_ptr<void> sp2;
shared_ptr<long> sp3;
weak_ptr<int> wp1;

owner_less<shared_ptr<int>> cmp;
cmp(sp1, sp2); // コンパイルエラー
cmp(sp1, wp1);
cmp(sp1, sp3); // コンパイルエラー
cmp(wp1, sp1);
cmp(wp1, wp1); // コンパイルエラー

C++1zでは、std::owner_lessクラステンプレートにvoidの特殊化版が定義され、そのバージョンでは関数テンプレートの関数呼び出し演算子を持つようになります:

// デフォルトテンプレート引数がvoidになり、
template<class T = void> struct owner_less;

// voidに対する特殊化が追加
template<> struct owner_less<void> {
  template<class T, class U>
    bool operator()(shared_ptr<T> const&, shared_ptr<U> const&) const;
  template<class T, class U>
    bool operator()(shared_ptr<T> const&, weak_ptr<U> const&) const;
  template<class T, class U>
    bool operator()(weak_ptr<T> const&, shared_ptr<U> const&) const;
  template<class T, class U>
    bool operator()(weak_ptr<T> const&, weak_ptr<U> const&) const;

  typedef unspecified is_transparent;
};

これによって、異なる要素型を持つスマートポインタや、shared_ptr<void>のような特殊な要素型を持つスマートポインタとの比較ができるようになります。

参照

お断り

この記事の内容は、C++1zが正式リリースされる際には変更される可能性があります。正式リリース後には、C++日本語リファレンスサイトcpprefjpの以下の階層の下に解説ページを用意する予定です。