Является ли gcc 4.8 или более ранним багги о регулярных выражениях?
Я пытаюсь использовать std:: regex в C++11 кусок кода, но кажется, что поддержка немного глючит. Пример:
#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
кроме того, регулярное выражение работает хорошо, если у меня есть только два альтернативных шаблона, например st|mt
, так что похоже, что последний не соответствует по некоторым причинам. Код хорошо работает с Компилятор Apple LLVM.
любые идеи о том, как решить эту проблему?
обновление одним из возможных решений является использование групп для реализации нескольких альтернатив, например,(st|mt)|tr
.
3 ответа:
<regex>
был реализован и выпущен в GCC 4.9.0.в вашей (более старой) версии GCC, это не выполнены.
что прототип
<regex>
код был добавлен, когда вся поддержка C++0x GCC была очень экспериментальный, отслеживая ранние проекты C++0x и будучи доступным для людей, чтобы экспериментировать. Это позволило людям найти проблемы и дать обратную связь в Комитет по стандартам до того, как стандарт был завершен. В то время многие люди были благодарны за то, что имели доступ к функциям bleeding edge задолго до того, как C++11 был завершен, и до того, как многие другие компиляторы предоставили любой поддержка, и эта обратная связь действительно помогла улучшить C++11. Это было хорошоTM.The
<regex>
код никогда не был в полезном состоянии, но был добавлен как незавершенное производство, как и многие другие биты кода в то время. Он был зарегистрирован и доступен для других, чтобы сотрудничать, если они хотел, с намерением, что это будет закончено в конечном итоге.так часто работает open source:отпустить раньше, часто выпускают -- к сожалению, в случае
<regex>
мы только получили раннюю часть права, а не часто часть, которая закончила бы реализацию.большинство частей библиотеки были более полными и теперь почти полностью реализованы, но
<regex>
не было, поэтому он остался в том же незавершенном состоянии, так как он был добавлен.серьезно, хотя, кто, хотя доставка реализации regex_search, которая только "возвращает false", была хорошей идеей?
это была не такая уж плохая идея несколько лет назад, когда C++0x все еще работал, и мы отправили много частичных реализаций. Никто не думал, что он будет оставаться непригодным для использования так долго, поэтому, оглядываясь назад, возможно, он должен был быть отключен и требовал макроса или встроенного времени, чтобы включить его. Но этот корабль давно. Есть экспортированные символы из библиотекиlibstdc++. so, которые зависят от кода регулярного выражения, поэтому простое удаление его (например, в GCC 4.8) не было бы тривиальным.
Функция Обнаружения
это фрагмент, чтобы обнаружить, если
libstdc++
реализация реализована с препроцессором C определяет:#include <regex> #if __cplusplus >= 201103L && \ (!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \ (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \ defined(_GLIBCXX_REGEX_STATE_LIMIT) || \ (defined(_GLIBCXX_RELEASE) && \ _GLIBCXX_RELEASE > 4))) #define HAVE_WORKING_REGEX 1 #else #define HAVE_WORKING_REGEX 0 #endif
макрос
_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT
и определена наbits/regex.tcc
in4.9.x
_GLIBCXX_REGEX_STATE_LIMIT
и определена наbits/regex_automatron.h
на5+
_GLIBCXX_RELEASE
добавлено7+
в результате ответ и является ли GCC major версиятестирование
вы можете проверить его с помощью GCC следующим образом:
cat << EOF | g++ --std=c++11 -x c++ - && ./a.out #include <regex> #if __cplusplus >= 201103L && \ (!defined(__GLIBCXX__) || (__cplusplus >= 201402L) || \ (defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \ defined(_GLIBCXX_REGEX_STATE_LIMIT) || \ (defined(_GLIBCXX_RELEASE) && \ _GLIBCXX_RELEASE > 4))) #define HAVE_WORKING_REGEX 1 #else #define HAVE_WORKING_REGEX 0 #endif #include <iostream> int main() { const std::regex regex(".*"); const std::string string = "This should match!"; const auto result = std::regex_search(string, regex); #if HAVE_WORKING_REGEX std::cerr << "<regex> works, look: " << std::boolalpha << result << std::endl; #else std::cerr << "<regex> doesn't work, look: " << std::boolalpha << result << std::endl; #endif return result ? EXIT_SUCCESS : EXIT_FAILURE; } EOF
результаты
вот некоторые результаты для различных компиляторов:
$ gcc --version gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-11) Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ./a.out <regex> doesn't work, look: false
$ gcc --version gcc (GCC) 6.2.1 20160830 Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ./a.out <regex> works, look: true
$ gcc --version gcc (Debian 4.9.2-10) 4.9.2 Copyright (C) 2014 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ./a.out <regex> works, look: true
$ gcc --version gcc (Ubuntu 6.2.0-5ubuntu12) 6.2.0 20161005 Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ./a.out <regex> works, look: true
$ gcc --version gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609 Copyright (C) 2015 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ ./a.out <regex> works, look: true
$ gcc --version gcc (GCC) 6.2.1 20160830 Copyright (C) 2016 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ clang --version clang version 3.9.0 (tags/RELEASE_390/final) Target: x86_64-unknown-linux-gnu Thread model: posix InstalledDir: /usr/bin $ ./a.out # compiled with 'clang -lstdc++' <regex> works, look: true
здесь будут драконы
это полностью не поддерживается и зависит от обнаружения частных макросов, которые разработчики GCC ввели элемент
bits/regex*
заголовки. Они могут измениться и уйти в в любое время. Надеюсь, они не будут удалены в текущем 4.9.х, 5.х, 6.X релизы, но они могут уйти в 7.х выпусках.если разработчики GCC добавили
#define _GLIBCXX_HAVE_WORKING_REGEX 1
(или что-то, намек намек подтолкнуть подтолкнуть) в 7.X релиз, который сохранился, этот фрагмент может быть обновлен, чтобы включить его,а более поздние выпуски GCC будут работать с приведенным выше фрагментом.насколько я знаю, все остальные компиляторы имеют а рабочий
<regex>
, когда__cplusplus >= 201103L
но YMMV.очевидно, что это может полностью сломать, если кто-то определил
_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT
или_GLIBCXX_REGEX_STATE_LIMIT
макросы внеstdc++-v3
заголовки.
на данный момент (используя std=c++14 в g++ (GCC) 4.9.2) все еще не принимает regex_match.
вот подход, который работает как regex_match, но вместо этого использует sregex_token_iterator. И он работает с G++.
string line="1a2b3c"; std::regex re("(\d)"); std::vector<std::string> inVector{ std::sregex_token_iterator(line.begin(), line.end(), re, 1), {} }; //prints all matches for(int i=0; i<inVector.size(); ++i) std::cout << i << ":" << inVector[i] << endl;
он будет печатать 1 2 3
вы можете прочитать ссылку sregex_token_iterator в: http://en.cppreference.com/w/cpp/regex/regex_token_iterator