Я пытаюсь использовать 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
,
<regex>
был реализован и выпущен в GCC 4.9.0.
В вашей (более старой) версии GCC это не реализованы.
Этот прототип <regex>
код был добавлен, когда вся поддержка GCC C ++ 0x была высоко экспериментальный, отслеживающий ранние черновики C ++ 0x и доступный для экспериментов. Это позволило людям находить проблемы и давать обратную связь стандартному комитету до того, как стандарт был окончательно доработан. В то время многие люди были благодарны за то, что получили доступ к новейшим возможностям задолго до завершения C ++ 11 и до того, как многие другие компиляторы предоставили любой поддержка, и эта обратная связь действительно помогла улучшить C ++ 11. Это было хорошоTM.
<regex>
код никогда не был в полезном состоянии, но был добавлен как незавершенный процесс, как и многие другие биты кода в то время. Он был зарегистрирован и предоставлен другим для сотрудничества, если они захотят, с намерением, что это будет в конечном итоге завершено.
Это часто, как работает с открытым исходным кодом: Выпуск рано, выпуск часто — к сожалению, в случае <regex>
мы правильно поняли только начальную часть, а не частую часть, которая бы закончила реализацию.
Большинство частей библиотеки были более полными и теперь почти полностью реализованы, но <regex>
не было, поэтому он остался в том же незавершенном состоянии, так как он был добавлен.
Серьезно, хотя, кто, хотя, что поставка реализации regex_search, которая только «возвращает ложь», была хорошей идеей?
Это была не плохая идея несколько лет назад, когда C ++ 0x все еще находился в стадии разработки, и мы поставили много частичных реализаций. Никто не думал, что он останется непригодным для использования в течение столь длительного времени, поэтому, оглядываясь назад, возможно, его следовало бы отключить, и для его включения требовалась опция макроса или встроенного времени. Но этот корабль давно отплыл. Есть экспортированные символы из libstdc ++. так библиотека, которая зависит от кода регулярного выражения, поэтому простое его удаление (например, в 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
в 4.9.x
_GLIBCXX_REGEX_STATE_LIMIT
является определенный в bits/regex_automatron.h
в 5+
_GLIBCXX_RELEASE
был добавлен в 7+
как результат этот ответ и является основной версией GCCВы можете проверить это с помощью 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.x, 5.x, 6.x, но они могут исчезнуть в выпусках 7.x.
Если разработчики 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