# Boost Property Map Library

Boost Property Map Libraryは、ジェネリックな、オブジェクト間のマッピングインターフェースを提供するという要請に、取り組んだ、小さなライブラリである。ライブラリのほとんどの部分は、インターフェース定義であり、コンセプトの集合として捕らえられる。それに加え、サポート用の種別タグ(category tag)、特性クラス(traits class)、さらには、プロパティマップのインターフェースを実装するいくつかのタイプがある。それらのクラスは、すべてのマッピングにおける要請をよく満たしているわけではない。むしろ、多くの、一般的な場合に適用できるインターフェースを、実装する方法を例示している。

## プロパティマップコンセプト(Property Map Concepts)

プロパティマップインターフェースは、コンセプトの集合により構成される。(コンセプト"concept"の定義を参照のこと[1][2]) コンセプトは、キーオブジェクトとそれに対応する値オブジェクトをマップする、広汎な目的に用いられるメカニズムであり、それゆえに、プロパティマップを使用するアルゴリズムからプロパティマップの実装詳細を隠している。プロパティマップへの要請として、キーと値オブジェクトの型を意図的にあいまいにし、最大限の柔軟性を許すことがある。プロパティマップへの操作がグローバル関数により行われるため、マップ操作関数をオーバーロードでき、ほとんど任意にプロパティマップのタイプとキーのタイプを使用することができる。プロパティマップのインターフェースは、get(), put(), operator[]の三つの関数により構成される。次に示す具体的な例(example.cpp)は、この三つの関数が、たくさんの人々と、それに関連付けられた住所をアクセスするために、どのように用いられるかを示す。 私たちは、ここでは、独立した関数テンプレートを用い、プロパティマップのコンセプトが使用されるプログラムの一部分を!!!!明確にしめす。main()関数では、`std::map`と`boost::associative_property_map`を用いたが、他のどんな型(あなたが作成したカスタムな型も含む)でも大丈夫だろうし、それらの型は、プロパティマップへの要請をみたすだろう。

    #include <iostream>
    #include <map>
    #include <string>
    #include <boost/property_map.hpp>

    template <typename AddressMap>
    void foo(AddressMap address)
    {
      typedef typename boost::property_traits<AddressMap>::value_type value_type;
      typedef typename boost::property_traits<AddressMap>::key_type key_type;

      value_type old_address, new_address;
      key_type fred = "Fred";
      old_address = get(address, fred);
      new_address = "384 Fitzpatrick Street";
      put(address, fred, new_address);

      key_type joe = "Joe";
      value_type& joes_address = address[joe];
      joes_address = "325 Cushing Avenue";
    }

    int
    main()
    {
      std::map<std::string, std::string> name2address;
      boost::associative_property_map< std::map<std::string, std::string> >
        address_map(name2address);

      name2address.insert(make_pair(std::string("Fred"),
    				std::string("710 West 13th Street")));
      name2address.insert(make_pair(std::string("Joe"),
    				std::string("710 West 13th Street")));

      foo(address_map);

      for (std::map<std::string, std::string>::iterator i = name2address.begin();
           i != name2address.end(); ++i)
        std::cout << i->first << ": " << i->second << "\n";

      return EXIT_SUCCESS;
    }

それぞれの属性マップオブジェクトに対し、値オブジェクトへの対応付けが可能な妥当なキーの集合がある。属性マップ関数を妥当ではないキーを用いて呼び出した場合には、結果は未定義である。属性マップコンセプトは、妥当なキーが生成や変更の方法を定めない。属性マップを使用する関数は、期待される妥当なキーの集合を、関数呼び出しの事前条件として、指定しなければならない。

属性マップの必要性はBoost Graph Libraryのデザインにおいて、明らかになった。Boost Graph Libraryのアルゴリズムは、頂点と稜に対応付けられた属性をアクセスするインターフェースを必要とした。

プロパティマップの数多くのカテゴリは、異なるアクセス能力を提供している：

readable(読み取り可能)
  関連付けられたプロパティのデータは、読み出すことができるのみである。 データは、値渡しで返される。問題領域における入力(たとえば、edgeやweight)を定義する多くのプロパティマップは、readableなプロパティマップとして定義することができる。

writeable(書き込み可能)
  関連付けられたプロパティに対する書き込みのみを行うことができる。 横優先検索ツリーのパスを記録するために用いられる親配列は、writable(書き込みのみ可能)なプロパティマップの例である。

read/write(読み取り/書き込み可能)
  関連付けられたプロパティに大して、読み出しと書き込みを行うことができる。 ダイクストラの最短経路探索アルゴリズムに用いられる距離プロパティは、読み出しと書き込みの両方の機能を提供する必要があるだろう。

lvalue
  関連付けられたプロパティはメモリ内に表現されており、参照を取得することができる。プロパティマップのlvalueカテゴリは、read/writeプロパティマップへの要請を満たす。

4つのプロパティマップカテゴリから分離して定義されるコンセプトがある。 これらのプロパティマップコンセプトは、以下にリストされる。また、それぞれのドキュメントがリンクされている。

- ReadablePropertyMap
- WritablePropertyMap
- ReadWritePropertyMap
- LvaluePropertyMap

## プロパティマップカテゴリタグ(Property Map Category Tags)

タグ構造体が、それぞれのプロパティマップのカテゴリごとに存在し、ヘッダ`<boost/property_map.hpp>`において定義される。

    namespace boost {

      struct readable_property_map_tag { };

      struct writable_property_map_tag { };

      struct read_write_property_map_tag :
        public readable_property_map_tag,
        public writable_property_map_tag { };

      struct lvalue_property_map_tag :
        public read_write_property_map_tag { };

    }

## プロパティマップ特性(Property Map Traits)

STLの`std::iterator_traits`クラスと同様に、プロパティマップで定義される型(キー型と値型、プロパティマップカテゴリ)の型推論に用いられる`boost::property_traits` クラス がある。また、`boost::property_traits`は、特殊化され、ポインタもプロパティマップのオブジェクトとして用いることができる。それに加え、プロパティマップ関数は、ポインタ型に対してオーバーロードされる。これらの用途に用いられる特性(traits)クラスと関数が、`<boost/property_map.hpp>`に定義される。

    namespace boost {

      template <typename PropertyMap>
      struct property_traits {
         typedef typename PropertyMap::key_type key_type;
         typedef typename PropertyMap::value_type value_type;
         typedef typename PropertyMap::category category;
      };

    }

## プロパティマップで定義される型

- C++のポインタ型
  次に示す`property_traits`の特殊化と、`put()`関数と`get()`関数のオーバーロードがC++のポインタ型を用いて、C++のポインタ型をプロパティマップとして用いることを可能とする。これらは、`boost/property_map.hpp`にて、定義される。より明確に説明すると、`T*`は、LvaluePropertyMapのモデルであり、与えられたキー型は、少なくとも、`std::ptrdiff_t`に変換可能でなければならない。

      namespace boost {
        // specialization for using pointers as property maps
        template <typename T>
        struct property_traits<T*> {
          typedef T value_type;
          typedef std::ptrdiff_t key_type;
          typedef random_access_iterator_pa_tag category;
        };

        // overloads of the property map functions for pointers
        template<>
        void put(T* pmap, std::ptrdiff_t k, const T& val) { pmap[k] = val;  }

        template<>
        const T& get(const T* pmap, std::ptrdiff_t k) { return pmap[k]; }

      }

- identity_property_map
- iterator_property_map
- associative_property_map
- const_associative_property_map

### 履歴

プロパティマップのインターフェースは、ジェネリックなグラフアルゴリズムに関するDietmar Kühl'の修士論文で述べられたdata accessorsを起源とする。 プロパティマップの概念は、Generic Graph Component Library (GGCL)の初期バージョン内における、decoratorsとしても現れている。また、Generic Graph Component Library (GGCL)は、現在、Boost Graph Library (BGL)となっている。プロパティマップを構築する主な動機は、グラフ内の頂点や稜に対応付けられたデータへのアクセスをサポートすることであった。しかしながら、プロパティマップの適用範囲は、これを、超えている。

### 謝辞

Dietmar Kühl へ。プロパティマップのメカニズムを持っての登場に感謝いたします。
Boostのメンバたちへ。プロパティマップインターフェースを発展させ、改善してくれたことに感謝いたします。
Dave Abrahamsへ。プロパティマップライブラリを含むBGLの査読を監督してくれたことに感謝いたします。

### 実装者への注釈

プロパティマップの複製のコストは、高くてはいけない。 なぜなら、プロパティマップは、しばしば値渡しされるからである。

Copyright © 2000-2002 | Jeremy Siek, Indiana University (jsiek@lsc.nd.edu)