# Boost.Function Tutorial

Boost.Function には 2 種類の文法がある。推奨文法と互換文法である。推奨文法は C++ にフィットし、考慮するテンプレートパラメータの数も減り、可読性を高める事が多い。しかし、コンパイラのバグのせいで、推奨文法が使えないコンパイラも有る。互換文法は Boost.Function がサポートする全てのコンパイラで使える。どちらの文法を使うかは、下の表を見て決めて欲しい。

推奨文法 | 互換文法
--- | ---
GNU C++ 2.95.x, 3.0.x, 3.1.x, 3.2 Comeau C++ 4.2.45.2 SGI MIPSpro 7.3.0 Intel C++ 5.0, 6.0 Compaq's cxx 6.2 | Microsoft Visual C++ 6.0, 7.0 Borland C++ 5.5.1 Sun WorkShop 6 update 2 C++ 5.3 Metrowerks CodeWarrior 8.1

あなたのコンパイラが表に無ければ、推奨文法を試してみて、結果を Boost MLに報告して欲しい。この表を最新に保つためだ。

## Basic Usage

関数オブジェクトのラッパを定義するには、 `function` クラステンプレートをインスタンス化するだけだ。テンプレート引数には、戻り値型と引数型を関数型形式で指定する。ある実装定義の最大値 (デフォルトは 10) までなら、引数は何個でも構わない。以下に、 2 つの `int` 型のパラメータを取り、`float` 型を返す関数オブジェクトのラッパ `f` の定義を示す。

推奨文法 | 互換文法
--- | ---
    boost::function<float (int x, int y)> f;
    boost::function2<float, int, int> f;

デフォルトでは、関数オブジェクトのラッパは空である。 `f` に代入する関数オブジェクトを作ろう。

    struct int_div {
      float operator()(int x, int y) const { return ((float)x)/y; };
    };

    f = int_div();

これで、関数オブジェクト `int_div` を呼び出す代わりに `f` を使える。

    std::cout << f(5, 3) << std::endl;

`f` には、互換性があれば、どんな関数オブジェクトでも代入できる。 `int_div` が 2 つの `long` 型の引数をとると宣言されていれば、自動的に暗黙の型変換が適用される。引数型に対する唯一の制限は、コピーコンストラクト可能な事である。だから、参照や配列さえ使える。

推奨文法 | 互換文法
--- | ---
    boost::function<void (int values[], int n, int& sum, float& avg)> sum_avg;
    boost::function4<void, int[], int, int&, float> sum_avg;

    void do_sum_avg(int values[], int n, int& sum, float& avg)
    {
      sum = 0;
      for (int i = 0; i < n; i++)
        sum += values[i];
      avg = (float)sum / n;
    }

    sum_avg = &do_sum_avg;

関数オブジェクトを格納していないラッパを呼び出すのは事前条件違反である。ヌルの関数ポインタを呼び出そうとするようなものだ。関数オブジェクトのラッパが空かどうかは `empty()` メソッドでチェックできる。もっと簡潔なのは、 bool 型の文脈でラッパを使う方法だ。ラッパは、空でなければ true と評価される。例えば、

    if (f)
      std::cout << f(5, 3) << std::endl;
    else
      std::cout << "f has no target, so it is unsafe to call" << std::endl;

ラッパを空にするには、 `clear()` メンバ関数を使う。

### Free functions

非メンバ関数へのポインタは、 const な関数呼出し演算子を持つ (インスタンスが1つだけ存在する) 関数オブジェクトの一種とみなせる。よって、関数オブジェクトのラッパに直接代入できる。

      float mul_ints(int x, int y) { return ((float)x) * y; }
      f = &mul_ints;

Microsoft Visual C++ version 6 を使う場合を除けば、本当は `&` は不要だ。

### Member functions

多くのシステムで、コールバックは特定のオブジェクトのメンバ関数を呼び出す事が多い。これは「引数の束縛」と呼ばれ、 Boost.Function の守備範囲外である。しかし、 Boost.Function には直接メンバ関数を扱う方法が有る。以下のコードのように使う。

推奨文法 | 互換文法
--- | ---
    struct X {
      int foo(int);
    };

    boost::function<int (X*, int)> f;

    f = &X::foo;

    X x;
    f(&x, 5);
    struct X {
      int foo(int);
    };

    boost::function2<int, X*, int> f;

    f = &X::foo;

    X x;
    f(&x, 5);

引数の束縛をサポートするライブラリはいくつか有る。その内 3 つを以下に要約する。

- Boost.Bind。このライブラリを使えば、あらゆる関数オブジェクトの引数を束縛できる。軽くて移植性が高い。
- C++ 標準ライブラリ。 `std::bind1st` と `std::mem_fun` を一緒に使って、メンバ関数ポインタと (その対象となる) オブジェクトを束縛したものは、 Boost.Function で使える。

  推奨文法 | 互換文法
  --- | ---
        struct X {
          int foo(int);
        };

        boost::function<int (int)> f;
        X x;
        f = std::bind1st(std::mem_fun(&X::foo), &x);

        f(5); // Call x.foo(5)
        struct X {
          int foo(int);
        };

        boost::function1<int, int> f;
        X x;
        f = std::bind1st(std::mem_fun(&X::foo), &x);

        f(5); // Call x.foo(5)

- Boost.Lambda ライブラリ。このライブラリは、自然な C++ の文法を使って関数オブジェクトを構築する強力な機構を提供する。 Lambda は、コンパイラが C++ 標準にかなり準拠していないと使えない。

### References to Functions

Boost.Function による関数オブジェクトのコピーが高価 (または不正) な場合が有る。そんな場合は、 Boost.Function に実際の関数オブジェクトの「参照」を格納させる事ができる。`ref` や `cref` を使う事で、関数オブジェクトの参照のラッパを作成できる。

推奨文法 | 互換文法
--- | ---
      stateful_type a_function_object;
      boost::function<int (int)> f;
      f = ref(a_function_object);

      boost::function<int (int)> f2(f);
      stateful_type a_function_object;
      boost::function1<int, int> f;
      f = ref(a_function_object);

      boost::function1<int, int> f2(f);

こうすれば、 `f` も `f2` も `a_function_object` のコピーを作成しない。さらに、関数オブジェクトの参照を使えば、 Boost.Function は代入、構築時に例外を起こさない。

Last modified: Fri Oct 11 05:40:00 EDT 2002

Japanese Translation Copyright © 2003 Hiroshi Ichikawa
オリジナルの、及びこの著作権表示が全ての複製の中に現れる限り、この文書の複製、利用、変更、販売そして配布を認める。このドキュメントは「あるがまま」に提供されており、いかなる明示的、暗黙的保証も行わない。また、いかなる目的に対しても、その利用が適していることを関知しない。

このドキュメントの対象: Boost Version 1.29.0
最新版ドキュメント (英語)