あめだまふぁくとりー

Boost.Graphとかできますん

static_property_mapとconstant_property_map

Boost.PropertyMapには指定した値を常に返すstatic_property_mapというプロパティマップがある.一方BGLにも指定した値を常に返すconstant_property_mapがある.前者は,後者はをインクルードすることで使用できる.それぞれのクラス定義は次のようになっている(一部省略).

template <class ValueType>
class static_property_map {
  public:
    static_property_map(ValueType value);
};

template <class Key, class Value>
struct constant_property_map {
    constant_property_map(const Value& value);
};

見て分かるとおりstatic_property_mapはkey_typeを指定しないのに対し,constant_property_mapはkey_typeを指定する必要がある.static_property_map内のkey_typeは常にvoidになっている.型の指定が一つしかないstatic_property_mapの方が楽でいいような気もするが,BGLではconstant_property_mapの代わりにstatic_property_mapを使用するとまずい場合がある.以下それ例

int main()
{
    Graph g;  // グラフの生成// 省略
    typedef graph_traits<Graph>::edge_descriptor Edge;
    boost::dynamic_properties dp;
    dp.property("name", make_constant_property<Edge>(std::string("edge")); // constant_property_mapで全ての枝のname属性に"edge"を指定
    dp.property("len", static_property_map<int>(5)); // 枝のlen属性に5を指定したいがエラー
    dp.property("node_id", get(vertex_index, g));
    write_graphviz_dp(std::cout, g, dp); // グラフをdot言語で出力
}

dynamic_propertiesを用いてグラフをdot言語にする場合,nameやlen等の属性が節点の属性なのか枝の属性なのかしる必要がある.その際にプロパティマップのkey_typeを用いてそれが行われるようになっているっぽい.そのためkey_typeがvoidのstatic_property_mapではうまくいかないようである.自分でBGLのコンセプトにマッチしたアルゴリズムを書いている場合でも問題になるときがあったのでBGLで用いるときはstatic_property_mapよりもconstant_property_mapを用いた方がよいと思われる.
BGLでない場合でもkey_typeの型が予め分かっているならconstant_property_mapを使えば間違ったkeyを渡したときにコンパイルエラーになるのでそうした方がいいだろう.

ところでdyanamic_propertiesを使ってグラフ全体,ノード全体,エッジ全体の属性を指定する方法ってないの?