¿Gcc 4.8 o anterior tiene fallos sobre expresiones regulares?

Estoy tratando de usar std :: regex en un código de C ++ 11, pero parece que el soporte es un poco problemático. Un ejemplo:

#include  #include  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; } 

productos:

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

cuando se comstack con gcc (MacPorts gcc47 4.7.1_2) 4.7.1, ya sea con

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

o

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

Además, la expresión regular funciona bien si solo tengo dos patrones alternativos, por ejemplo, st|mt , por lo que parece que el último no coincide por alguna razón. El código funciona bien con el comstackdor Apple LLVM.

¿Alguna idea sobre cómo resolver el problema?

Actualizar una posible solución es usar grupos para implementar múltiples alternativas, por ej. (st|mt)|tr .

fue implementado y lanzado en GCC 4.9.0.

En su versión (anterior) de GCC, no está implementado .

Ese código prototipo se agregó cuando todo el soporte de C ++ 0x de GCC era altamente experimental, rastreaba borradores iniciales de C ++ 0x y estaba disponible para que las personas experimentaran. Eso permitió a las personas a encontrar problemas y dar su opinión al comité estándar antes de que se finalizara el estándar. En ese momento, muchas personas estaban agradecidas de haber tenido acceso a las características de punta de fábrica mucho antes de que C ++ 11 estuviera terminado y antes de que muchos otros comstackdores proporcionaran soporte, y esa retroalimentación realmente ayudó a mejorar C ++ 11. Esta fue una buena cosa TM .

El código nunca estuvo en un estado útil, pero se agregó como un trabajo en progreso como muchos otros bits de código en ese momento. Fue registrado y puesto a disposición para que otros colaboraran si quisieran, con la intención de que finalmente se terminara.

Así es como funciona el código abierto: Libere pronto, libere a menudo ; desafortunadamente en el caso de solo conseguimos la parte inicial correcta y no la parte que a menudo habría terminado la implementación.

La mayoría de las partes de la biblioteca eran más completas y ahora están casi completamente implementadas, pero no lo habían estado, por lo que se mantuvieron en el mismo estado sin terminar desde que se agregaron.

En serio, ¿quién pensó que enviar una implementación de regex_search que solo devolviera “false” era una buena idea?

No fue tan mala idea hace unos años, cuando C ++ 0x todavía era un trabajo en progreso y enviamos muchas implementaciones parciales. Nadie pensó que permanecería inutilizable por tanto tiempo, en retrospectiva, tal vez debería haber sido deshabilitado y requería una opción macro o incorporada para habilitarlo. Pero ese barco navegó hace mucho tiempo. Hay símbolos exportados de la biblioteca libstdc ++. So que dependen del código regex, por lo que simplemente eliminarlo (en, por ejemplo, GCC 4.8) no habría sido trivial.

Detección de funciones

Este es un fragmento para detectar si la implementación libstdc++ se implementa con preprocesador C define:

 #include  #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 

Macros

  • _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT se define en bits/regex.tcc en 4.9.x
  • _GLIBCXX_REGEX_STATE_LIMIT se define en bits/regex_automatron.h en 5+
  • _GLIBCXX_RELEASE se agregó a 7+ como resultado de esta respuesta y es la versión principal de GCC

Pruebas

Puedes probarlo con GCC de la siguiente manera:

 cat << EOF | g++ --std=c++11 -x c++ - && ./a.out #include  #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  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 << " works, look: " << std::boolalpha << result << std::endl; #else std::cerr << " doesn't work, look: " << std::boolalpha << result << std::endl; #endif return result ? EXIT_SUCCESS : EXIT_FAILURE; } EOF 

Resultados

Aquí hay algunos resultados para varios comstackdores:


 $ 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  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  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  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  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  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++'  works, look: true 

Aquí hay dragones

Esto no se admite por completo y se basa en la detección de macros privadas que los desarrolladores de GCC han puesto en los encabezados bits/regex* . Podrían cambiar y desaparecer en cualquier momento . Con suerte, no se eliminarán en las versiones actuales 4.9.x, 5.x, 6.x, pero podrían desaparecer en las versiones 7.x.

Si los desarrolladores de GCC añadieron #define _GLIBCXX_HAVE_WORKING_REGEX 1 (o algo así como sugerencia de sugerencia), en la versión 7.x que persistía, este fragmento podría actualizarse para incluir eso y las versiones posteriores de GCC funcionarían con el fragmento anterior.

Por lo que yo sé, todos los demás comstackdores tienen un cuando __cplusplus >= 201103L pero YMMV.

Obviamente, esto se rompería por completo si alguien definiera las macros _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT o _GLIBCXX_REGEX_STATE_LIMIT fuera de los stdc++-v3 de stdc++-v3 .

En este momento (usando std = c ++ 14 en g ++ (GCC) 4.9.2) todavía no acepta regex_match.

Aquí hay un enfoque que funciona como regex_match pero que usa sregex_token_iterator en su lugar. Y funciona con g ++.

 string line="1a2b3c"; std::regex re("(\\d)"); std::vector inVector{ std::sregex_token_iterator(line.begin(), line.end(), re, 1), {} }; //prints all matches for(int i=0; i 

imprimirá 1 2 3

Puede leer la referencia sregex_token_iterator en: http://en.cppreference.com/w/cpp/regex/regex_token_iterator