C++11 の正規表現ライブラリの仕様の曖昧な部分を指摘し、現実の実装のぶれを例示します。
ECMA-262 では、Multiline について以下のような定義が存在します。
^
や $
は改行文字の直後や直前にもそれぞれマッチし、
false ならばマッチしない。(文字列の先頭と最後にはそれぞれ常にマッチする)
ところが C++11 n3485 には Multiline についての言及はありません。
したがって ECMA-262 のデフォルトの動作、つまり Multiline=false が C++11 で期待される動作ということになるので、
^
や $
は改行文字の直後や直前にはそれぞれ決してマッチしないということになります。
Multiline=false であると解釈すると、以下のフラグの存在意義がなくなります。
^
が文字列の先頭にマッチしないようにする。$
が文字列の最後にマッチしないようにする。
これらのフラグを使用した場合、
^
や $
は決してマッチしない正規表現ということになり実用的な意味が失われます。
ところが Multiline=true であると解釈すれば、
改行文字を含む長い文章の一部を取り出した文字列に対してマッチを行うことを考えた場合に
^
や $
が改行の直後や直前にマッチするので、
行単位のマッチを行うことが可能になります。
たとえば regex_replace や regex_iterator などで改行を含む文章を処理する場合に役に立つことが予想されます。
仕様策定時点では Multiline=true を想定していたのではないか、 という推測ができますが現在の仕様では false になってしまうので現実実装に混乱が生じています。 曖昧な仕様を明確にする必要があります。
C++11 n3485 §28.11.2 [re.alg.match] p2 では regex_match について次のような定義がなされています。
Effects: Determines whether there is a match between the regular expression e, and all of the character sequence [first,last). The parameter flags is used to control how the expression is matched against the character sequence. Returns true if such a match exists, false otherwise.
この文章の前半は異なる解釈をすることが可能です。
\z
が追加されているかのように動作する。(\z
は Perl の正規表現で、文字列の最後のみにマッチする)
この解釈のぶれによって ECMAScript フラグで作成された正規表現に以下のような微妙な違いが生じます。
std::regex e("Get|GetValue");
"GetValue"
全体にマッチすることはありません。
というのは、ECMAScript では左側から順番にマッチするかどうかを判定し、最初に見つかったマッチが採用されるからです。
したがって |
の左側の "Get"
がマッチするので、
右側の "GetValue"
が考慮されることはありません。
"Get"
となります。"Get"
は文字列全体ではないので、false を返します。
\z
が追加されているかのように動作、
つまり e が (?:Get|GetValue)\z
であるかのように動作するので
その検索結果は "GetValue"
となります。
マッチが成功したので true を返します。
仕様が曖昧といえば曖昧であるものの、1 の解釈を行うのはかなり無理があるのではないかと思います。 この問題は C++ 標準化委員会に既に報告されています。