1. ホーム
  2. c++

[解決済み] gcc 4.8以前は正規表現にバグがあるのでしょうか?

2022-12-06 13:12:12

質問

C++11 のコードで std::regex を使用しようとしていますが、サポートに少しバグがあるようです。例を挙げます。

#include <regex>
#include <iostream>

int main (int argc, const char * argv[]) {
    std::regex r("st|mt|tr");
    std::cerr << "st|mt|tr" << " matches st? " << std::regex_match("st", r) << std::endl;
    std::cerr << "st|mt|tr" << " matches mt? " << std::regex_match("mt", r) << std::endl;
    std::cerr << "st|mt|tr" << " matches tr? " << std::regex_match("tr", r) << std::endl;
}

の出力があります。

st|mt|tr matches st? 1
st|mt|tr matches mt? 1
st|mt|tr matches tr? 0

gcc (MacPorts gcc47 4.7.1_2) 4.7.1 でコンパイルした場合、以下のどちらかの方法でコンパイルできます。

g++ *.cc -o test -std=c++11
g++ *.cc -o test -std=c++0x

または

g++ *.cc -o test -std=gnu++0x

さらに、正規表現は2つの代替パターンがある場合にうまく機能します。 st|mt のように、2つのパターンがある場合、正規表現はうまく機能するので、最後の1つは何らかの理由でマッチしないように見えます。このコードは Apple の LLVM コンパイラーでうまく動作します。

この問題を解決する方法について何かアイデアはありますか?

アップデートについて のように、グループを使って複数の選択肢を実装することが考えられます。 (st|mt)|tr .

どのように解決するのですか?

<regex> は GCC 4.9.0 で実装され、リリースされました。

あなたの(古い)バージョンのGCCでは、それは が実装されていません。 .

そのプロトタイプ <regex> のコードは、GCCのすべてのC++0xサポートが 非常に 初期の C++0x ドラフトを追跡し、人々が実験するために利用できるようにされていました。これによって、人々は標準が最終的に決定される前に問題を発見し、標準委員会にフィードバックをすることができました。当時、多くの人が、C++11 が完成するずっと前、そして他の多くのコンパイラーが提供するよりも前に、最先端の機能にアクセスできたことに感謝していました。 任意の サポートが提供される前に、C++11 が完成するずっと前から最先端の機能にアクセスできたことに感謝し、そのフィードバックは C++11 の改善に大いに役立ちました。 これは良いことでした。 TM .

<regex> のコードは決して有用な状態ではありませんでしたが、当時の他の多くのコードと同様に作業中として追加されました。それはチェックインされ、他の人が望むなら共同作業できるようにされ、最終的に完成することを意図していました。

これがオープンソースの仕組みです。 早くリリースし、頻繁にリリースする -- の場合、残念ながら <regex> の場合、残念ながら、初期の部分だけが正しく、実装を完成させるはずの頻繁な部分については正しくありませんでした。

ライブラリのほとんどの部分はより完成度が高く、現在ではほぼ完全に実装されていますが <regex> はまだ実装されていなかったので、追加されて以来、未完成の状態のままでした。

真面目な話、"return false" しかしない regex_search の実装を出荷することが良いアイデアだと考えたのは誰だったのでしょうか?

数年前、C++0x がまだ未完成で、多くの部分的な実装を出荷していたときは、それほど悪い考えではなかったのです。誰もこれほど長い間使用できないままだとは思わなかったので、今にして思えば、これを無効にし、マクロまたはビルトイン タイム オプションで有効にする必要があったのかもしれません。しかし、その船はとっくの昔に出航しています。のエクスポートされたシンボルがあります。 libstdc++.so ライブラリからエクスポートされたシンボルがあり、それは正規表現コードに依存しているので、(たとえば GCC 4.8 で) 単にそれを削除することは些細なことではないでしょう。