Czy gcc 4.8 lub wcześniejszy błąd dotyczy wyrażeń regularnych?
Próbuję użyć std::regex w części kodu C++11, ale wygląda na to, że obsługa jest trochę błędna. Przykład:
#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;
}
Wyjścia:
st|mt|tr matches st? 1
st|mt|tr matches mt? 1
st|mt|tr matches tr? 0
Po skompilowaniu z gcc (MacPorts gcc47 4.7.1_2) 4.7.1, albo z
g++ *.cc -o test -std=c++11
g++ *.cc -o test -std=c++0x
Lub
g++ *.cc -o test -std=gnu++0x
Poza tym regex działa dobrze, jeśli mam tylko dwa alternatywne wzory, np. st|mt
, więc wygląda na to, że ostatni nie jest dopasowany z pewnych powodów. Kod działa dobrze z kompilatorem Apple LLVM.
Wszelkie pomysły o tym, jak rozwiązać problem?
Update jednym z możliwych rozwiązań jest użycie grup do zaimplementowania wielu alternatyw, np. (st|mt)|tr
.
3 answers
<regex>
został zaimplementowany i wydany w GCC 4.9.0.
W Twojej (starszej) wersji GCC jest nie zaimplementowana.
Ten prototyp <regex>
kod został dodany, gdy cała obsługa C++0x GCC była wysoce eksperymentalna, śledząc wczesne szkice C++0x i udostępniając je ludziom do eksperymentowania. Pozwoliło to ludziom znaleźć problemy i przekazać opinię Komitetowi ds. standardów przed sfinalizowaniem normy. W tym czasie wiele osób było wdzięcznych aby mieć dostęp do funkcji bleeding edge na długo przed ukończeniem C++11 i zanim wiele innych kompilatorów zapewniło jakiekolwiek wsparcie, a te opinie naprawdę pomogły ulepszyć C++11. To była dobra rzeczTM .
Kod <regex>
nigdy nie był użyteczny, ale został dodany jako praca w toku, jak wiele innych bitów kodu w tym czasie. Został on sprawdzony i udostępniony innym do współpracy, jeśli chcą, z zamiarem, że zostanie ukończony w końcu.
Tak często działa open source: Release early, release czesto -- niestety w przypadku <regex>
mamy tylko poprawną część wczesną, a nie często część, która skończyłaby implementację.
Większość części biblioteki była bardziej kompletna i obecnie jest prawie w pełni zaimplementowana, ale <regex>
nie była, więc pozostała w tym samym niedokończonym stanie, odkąd została dodana.
Poważnie choć, kto choć, że wysyłka an implementacja regex_search, która tylko "return false" była dobrym pomysłem?
To nie był taki zły pomysł kilka lat temu, kiedy C++0x był jeszcze w toku i wysłaliśmy wiele częściowych implementacji. Nikt nie sądził, że pozostanie bezużyteczny przez tak długi czas, więc z perspektywy czasu może powinien być wyłączony i wymagał opcji makra lub wbudowanej w czasie, aby go włączyć. Ale ten statek odpłynął dawno temu. Są eksportowane symbole z libstdc++. tak więc biblioteka, która zależy od kodu regex, więc po prostu usunięcie go (np. w GCC 4.8) nie byłoby trywialne.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-28 23:06:12
Wykrywanie Funkcji
Jest to fragment do wykrycia, czy implementacja libstdc++
jest zaimplementowana z preprocesorem C definiuje:
#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
Makra
-
_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT
jest zdefiniowane wbits/regex.tcc
w4.9.x
-
_GLIBCXX_REGEX_STATE_LIMIT
jest zdefiniowane wbits/regex_automatron.h
W5+
-
_GLIBCXX_RELEASE
został dodany do7+
w wyniku tej odpowiedzi i jest główną wersją gcc
Testowanie
Można go przetestować z GCC jak to:
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
Wyniki
Oto wyniki dla różnych kompilatorów:
$ 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
Here be Dragons
Jest to całkowicie nieobsługiwane i polega na wykrywaniu prywatnych makr, które programiści GCC umieścili w nagłówkach bits/regex*
. Mogą się zmienić i odejść o w każdej chwili . Mam nadzieję, że nie zostaną usunięte w obecnej wersji 4.9.x, 5.x, 6.x wypuszcza, ale mogą odejdź w 7.x releases.
Jeśli deweloperzy GCC dodali #define _GLIBCXX_HAVE_WORKING_REGEX 1
(lub coś, podpowiedź podpowiedź nudge nudge) w 7.wersja X, która utrzymywała się, ten fragment może zostać zaktualizowany, aby zawierał ten fragment, a późniejsze wydania GCC będą działać z fragmentem powyżej.
Z tego co wiem, wszystkie inne Kompilatory mają działające <regex>
Kiedy __cplusplus >= 201103L
ale YMMV.
Oczywiście byłoby to całkowicie złamane, gdyby ktoś zdefiniował makra _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT
lub _GLIBCXX_REGEX_STATE_LIMIT
poza nagłówkami stdc++-v3
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-11 14:42:53
W tej chwili (używanie std = c++14 W g++ (GCC) 4.9.2) nadal nie akceptuje regex_match.
Oto podejście, które działa jak regex_match, ale zamiast tego używa sortex_token_iterator. I działa z 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;
Wydrukuje 1 2 3
Możesz przeczytać referencję sregex_token_iterator w: http://en.cppreference.com/w/cpp/regex/regex_token_iterator
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-10 18:32:30