Boost 1.35.0 のビルドのバッドノウハウ

  1. Boost 1.35.0 になってビルドの方法が変わってて,単に bjam 動かしただけでは以下の設定しかビルドされにゃい
    • リリースビルドで
    • マルチスレッドで
    • 共有ライブラリで
    • ランタイムを動的リンクする
  2. ./configure && make install も同じっぽ?
  3. autolink に頼ってたりすると,以前のバージョンではビルドされていたライブラリが見つからない場合があるのでリンクでコケーッコココこける (原因に気づきにくい)
  4. 以前のように全部の組み合わせをビルドするには bjam --build-type=complete (bjam --help 参照のこと)
  5. で, Boost.Regex のビルドで ICU を使う設定のとき --build-type=complete を指定しているとこける
  6. ↑がこけるのは libs/regex/build/Jamfile.v2 のバグ (ICU の共有ライブラリを引っ張ってくるときに runtime-link=static と conflict してるっぽ?)
  7. とりあえず bjam --build-type=complete の代わりに bjam debug release threading=single,multi link=static,shared runtime-link=shared でもいけることはいける (Boost.Regex 以外のライブラリにおいて runtime-link=static なものがビルドされないけど)
  8. バグを再現させてみる
  9. libs/regex/build/Jamfile.v2 を修正して ICU 付で --build-type=complete できるようにする
  10. \(^o^)/ やたー!とおた! (今ココ)
  11. SVN の HEAD で直っているかどうか確認する
  12. libs/regex/build/Jamfile.v2 のパッチ作るるるぅ〜

Multiple Placement Construction

http://d.hatena.ne.jp/faith_and_brave/20080526/1211793189
>曲芸的なアプローチ
というのはつまりヒロイン追加のコンシューマ版が発売されて,それがPCに逆移植されて,なおかつクリスマスやらサマーバケーションやらことあるごとに……じゃなかった.今の無視ね.これは,コンパイラの最適化がある程度上手く機能するという楽観的な前提をおけば実装できるんじゃねー.いや,知らんけど?っていうか,まさにこれをやりたくて考えたのが
http://d.hatena.ne.jp/Cryolite/20080314#p1
だしにゃー.いちおー, Delegating Constructors の存在を前提しとけば std::pair / std::tuple の inplace construction にも一般化できるはーずー.知らんけど?

文字列は文字列の連結という2項演算に関して semigroup ですよ.あー,いや, monoid か……なんていちいち考えるっぽ?

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2645.pdf
いや,こういう最も原初的で代数的な concept から組み立てあげる方向性は,まったく間違ってはいないし, STL (によらず汎用プログラミング全般) 的にいって王道的進化だとは思うし,非常に個人的な立場から言えば大歓迎なんだけれど.なんていうか……底知れぬ危惧ががが.
http://d.hatena.ne.jp/Cryolite/20070307#c1173362210
#っていうか,上のリンク先のコメントを書いたときの私は,どうやら "accumulate というアルゴリズム" という言葉を, x_1 \oplus x_2 \oplus \dots を計算するアルゴリズム,という意味で使っていたようで,それで「(この意味での) "accumulate というアルゴリズム" が well-defined であるためには semigroup じゃないといけない」という趣旨で,「accumulate というアルゴリズムにおける,値型に対するもっとも緩く汎用な制約は半群 semigroup であること」と口走っていたようです.んぐゎ, C++ の標準ライブラリにおいて定義されている std::accumulate は交換則要りません. std::accumulate の定義は「左から順番に演算した結果 ((x_1 \oplus x_2) \oplus \dots) を返す」なので.このコメント書いたときの私は一体何を考えていたのでしょうか?ただ, std::accumulate 使う人はやはり semigroup という概念を知っていたほうが良い.つまり semigroup であるという情報が分かっていれば, std::accumulate の計算において,てけとーな場所から演算していっても構わなくなるので,実装がこれを活かしてより最適な特殊化を提供する可能性が考えられる.従って, semigroup という概念を把握していないと (特殊化を活かせないという意味で) 損する可能性がある.semigroup であることを活かした特殊化の例としては,上の PDF では (単位元を取れるという要請も付けて) unrolling を引き合いに出していますが,他にも自動並列化ができる,などといった具合.
#あと,自分のコメントの「2項関数の適用順序が固定されるならば左 (右) 半群」は,もう正直書いた本人も意図が分からない.多分, accumulate 使って文字列の列をつなげ,ファイルパスを作るようなことを想定していたような気がするような! (後付け設定)

structual よりも non-intrusive だと思うにゃー

http://www.kmonos.net/wlog/85.html#_0905080505
う〜ん, structural かどうかではなくて non-intrusive かどうかっていう軸の方が重要だと思うんですけれどどうなんでしょうかねー.
non-intrusive という言葉を明快に定義してくれている書籍なりサイトなりが少なくてアレなんですが,オレオレな理解で行くと, non-intrusive とは,あるデータ型 T が何らかの制約 (これこれこういうインタフェイスを持ってないといけないよ,という決まり) を満足しているかどうか,に関する記述が T の定義と独立に記述することができる,あるいはもはや制約の充足に関する記述自体不要,ということだと理解しています.
歴史的な流れでいうと STL の存在が大きいのはこれは k.inaba さんの指摘どおりだと自分も思っていて,たとえば STLアルゴリズムはポインタ型もイテレータとして扱えなければならなかった.ところが, STL において機能するように,ポインタ型という型の定義に侵入的な変更 (たとえばポインタ型が新たに何か基底クラスを継承するようにする,といった変更) を加えることは許されなかった.何せ組み込み型だし. STL ではどうしたかというと,「operator* が定義されていて,その意味は〜〜で,計算量は〜〜で」「operator++ が定義されていて,その意味が〜〜で,計算量は〜〜で」以下云々……という制約を満たす型は全部イテレータであるとして,ポインタ型も std::vector::iteratorイテレータとして扱えるようにした.
あるコンポーネント C が, C の存在をまったくもって想定していなかった別のコンポーネント C' に対しても, C' に対して侵入的な変更を加えることなく機能する.具体的な話に置き換えると, STL というコンポーネントの登場をまったくもって想定していなかった (C 由来の) ポインタ型が,その型の定義にまったく侵入的な改変を被ることなく, STL というコンポーネントにおいて普通に機能する.こういう特徴を,少なくとも C++ のコミュニティでは極めて重要視しているように思える.
しかし, structual polymorphism はこういう特徴を持つための十分条件に過ぎないんじゃないだろうか.
上記のように「STL がポインタ型も汎用に扱える」手段として,果たして structual polymorphism という選択だけしかなかったのか?というと自分の見解では明らかに NO であって,たとえば,

template<typename T>
RandomAccessIterator<T*>;

という記述で (もちろんこの記述は C++03 の記述ではありませんが),あらゆるポインタ型が RandomAccessIterator という制約を満足していることを明示的に表明できる,というあり方は多分ありえた.この書き方は, (nominal/structual という言葉の厳密な定義を知らないので間違っているかも知れませんが) nominal である,というべきでしょう.
structual ならば制約の充足の可否がインタフェイス (シグネチャ) の有無によって暗黙に決定されるため,この意味で non-intrusive (そもそも制約の充足を明記する必要すらない) なのですが, structual polymorphism という選択以外に,たとえば上記のように nominal かつ non-intrusive という記述ができる,という選択もあって良いはず.ただ,歴史的な背景,技術的未成熟,言語機能,言語機能の実装その他もろもろの関係から, STL が登場した当時においては structual polymorphism という唯一の選択を持って non-intrusiveness を達成するしかなかった,というのが自分の理解.
structual か, nominal (かつ non-intrusive) かは,non-intrusiveness を達成するという目的においては,最終的には,どちらが良い/悪いとかを決定できる類のものではないのではないかな,と.単に non-intrusiveness を達成するための選択肢として C++ プログラマの道具箱にこの2つが入っている,そういう類のものかと思います.実際, nominal な記述によるインタフェイス記述の階層化は,型が表す概念の間に明快な階層を見出せるならば,上手く概念上の構造ととインタフェイス記述の構造が合致し,これは subtyping の特徴を長所として上手く引き出せると考えられます.従って,この特徴を温存しながら non-intrusive な形で書きたいというのは,少なくとも選択肢としてはあってしかるべきじゃないかにゃーと,そう思うんですが眠い.

なんで requirement に関する推論が欲しくなったかというと,以下のようなのを見てたらうにゅーんっていう.
たとえば,

// とりあえず細かいことはおいといて,「型 T はデフォルトコンストラクタを持ってる」という制約の記述だと思って!
concept DefaultConstructible<typename T>
{
  T::T();
}

template<class T>
requires DefaultConstructible<T> // 関数テンプレート f は,その型パラメタ T が
                                 // デフォルトコンストラクタを持っていないといけない,という記述
T f()
{
  // 関数テンプレートの実装では,制約で宣言したインタフェイスしか*使ってはならない*.
  // たとえばここの f の実装では, DefaultConstructible<T> という制約の宣言から導出できる
  // インタフェイスの集合 (T に対するデフォルトコンストラクタ) しか*使ってはならない*.
  return T();
}

で,まぁ,この f の実装は怒られるんですけれどね.デフォルトコンストラクタしか使ってない(?)のにねぇ……っていう.
上記のはまだわかりやすいですけれど

concept DefaultConstructible<typename T>
{
  T::T();
}

template<class T>
requires DefaultConstructible<T>
void f()
{
  T t;
  T &r = t;
}

これもまた f の定義時点で怒られる (ハズ……型 T に一体デフォルトコンストラクタ以外の何が必要だとっ!?) んですが,こういうのになるとパッと見て一体何が間違いなのやら……っていう.
こういうのが (今現在の proposal に厳密に従うと) テンプレートの定義時点で事細かにはじかれる (まぁ,なんて厳しいコンパイラなんでしょう!) ので,上に上げたときに「すい」そ,下に「ろん」ちょっとやってみよっか,でして…….
こういう煩わしさは concept の継承(Generic Programming@C++ 的にかっちょ良く refinement って言おうね!) ガンガン使って concept 間の含意関係書いとけばかなりの程度解決する……ってか,含意関係のために refinement 使いまくってたらすぐに名前が曖昧になる (ダイアモンドだね〜 あぁ〜 あぁ〜♪) んじゃねー……あれ?もしかして名前の重複許すのかっ!?って調べたらやっぱり名前の重複許してた(^o^)キャー.

14.9.3.1 Concept member lookup

5 When name lookup in a concept scope C results in an overload seta set of associated functions, duplicate associated functions are removed from the overload set. If more than one associated function in the overload set has the same signature, the associated function found first by a depth-first traversal of the refinement clauses of C starting at C will be retained and the other associated functions will be removed as duplicates. [ Example:

concept A {
  T f(T); // #1a
}
concept B {
  T f(T); // #1b
  T g(T); // #2a
}
concept C : A, B {
  T g(T); // #2b
}
template
requires C
void h(T x) {
  C::f(x); // overload set contains #1a; #1b was removed as a duplicate
  C::g(x); // overload set contains #2b; #2a was removed as a duplicate
}
—end example ]

ヽ(゚∀゚)ノワーイ.いや,わーいじゃなくて 実装の多重継承許さない言語ならできて当然だろうし (e.g.), C++0x の concept においても (実装が書けないんだから) 実装の曖昧性が起きないから特に否定する理由ないし.
#あーれー? concept に default implementation 書いてたらまずいことが起きるんじゃ?