2. 参照ラッパ

概要

ジェネリックなアルゴリズムなど、多くの関数テンプレートでは引数が値渡しになってしまいます。しかし、当然のことながら、大きなオブジェクトを参照渡しするのは効率が悪いですし、場合によっては、関数内で更新した結果を呼び出し側にも反映したいといったこともあるでしょう。

このような場合には、std::tr1::ref 関数テンプレートを使用することで、擬似的に参照渡しにすることができます。

ヘッダ

Boost C++ Libraries では、<boost/ref.hpp> という専用のヘッダファイルを使用しますが、TR1 で参照ラッパを使用するには、<functional> をインクルードする必要があります。

ref および cref

namespace std {
  namespace tr1 {

    template <class T> class reference_wrapper
      : public unary_function<T1, R> // 下記参照
      : public binary_function<T1, T2, R> // 下記参照
    {
    public :
      // 型
      typedef T type; 
      typedef 下記参照 result_type; // 常に定義されるとは限らない

      // 構築/コピー/解体
      explicit reference_wrapper(T&);
      reference_wrapper(const reference_wrapper<T>& x);

      // 代入
      reference_wrapper& operator=(const reference_wrapper<T>& x);

      // アクセス
      operator T& () const;
      T& get() const;

      // 呼出し
      template <class T1, class T2, ..., class TN>
      typename result_of<T(T1, T2, ..., TN)>::type
        operator() (T1&, T2&, ..., TN&) const;
    };

    template <class T> reference_wrapper<T> ref(T&);
    template <class T> reference_wrapper<const T> cref(const T&);

    template <class T> reference_wrapper<T> ref(reference_wrapper<T>);
    template <class T> reference_wrapper<const T> cref(reference_wrapper<T>);

  }
}

元になった boost::ref とは微妙に仕様が異なりますのでご注意ください。例えば、Boost C++ Libraries には、reference_wrapper を受け取る ref 関数テンプレートがありません。一方、TR1 には、is_reference_wrapperunwrap_reference、また reference_wrapper::get_pointer が存在しません。

関数オブジェクトへの対応

もう一点、Boost C++ Libraries との大きな違いは、関数オブジェクトへの対応です。boost::ref でも関数オブジェクトを指定することはできましたが、関数呼出し演算子が多重定義されていないために、実際には get メンバ関数を介して呼び出さなければなりません。しかし、TR1 ではその問題が解消されているようです。

result_type

result_type は、T をベースとした型で、次のようになります。

  • T が関数型(または関数への参照型・ポインタ型)の場合、result_typeT の返却型の別名
  • T がメンバ関数へのポインタ型の場合、result_typeT の返却型の別名
  • Tresult_type という名のメンバを持つクラス型の場合、result_typeT::result_type の別名
  • それ以外の場合、result_type は定義されない。
このエントリーを含むはてなブックマーク