¿Es esa una característica o un error de clang c ++ 11 std ::regex_match?

 C Programming >> Programación C >  >> Tags >> Clang
¿Es esa una característica o un error de clang c ++ 11 std ::regex_match?


Noté que una expresión regular, que contiene dos patrones con la condición OR, no coincide con una cadena de muestra si el primer patrón es una parte inicial del segundo patrón (probado en clang 3.5 y clang 3.8):


std::regex_match("ab", std::regex("(ab|a)")) == true

pero


std::regex_match("ab", std::regex("(a|ab)")) == false

Creo que true es lógicamente correcto en ambos casos.


Sonido y OSX:


$ cat > test.cpp
#include <string>
#include <regex>
#include <iostream>
int main() {
std::cout << std::regex_match("ab", std::regex("(a|ab)")) << std::endl;
std::cout << std::regex_match("ab", std::regex("(ab|a)")) << std::endl;
return 0;
}
^C
$ clang++ -v
Apple LLVM version 8.1.0 (clang-802.0.41)
Target: x86_64-apple-darwin16.5.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
$ clang++ ./test.cpp -o test
$ ./test
0
1

Clang y FreeBSD:


$ cat > test.cpp
#include <string>
#include <regex>
#include <iostream>
int main() {
std::cout << std::regex_match("ab", std::regex("(a|ab)")) << std::endl;
std::cout << std::regex_match("ab", std::regex("(ab|a)")) << std::endl;
return 0;
}
^C
$ clang++ -v
FreeBSD clang version 3.8.0 (tags/RELEASE_380/final 262564) (based on LLVM 3.8.0)
Target: x86_64-unknown-freebsd11.0
Thread model: posix
InstalledDir: /usr/bin
$ clang++ ./test.cpp -o test
$ ./test
0
1

Linux y CCG:


$ cat > test.cpp
#include <string>
#include <regex>
#include <iostream>
int main() {
std::cout << std::regex_match("ab", std::regex("(a|ab)")) << std::endl;
std::cout << std::regex_match("ab", std::regex("(ab|a)")) << std::endl;
return 0;
}
^C
$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.1-2ubuntu1~16.04' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 5.4.1 20160904 (Ubuntu 5.4.1-2ubuntu1~16.04)
$ g++ -std=gnu++11 ./test.cpp -o test
$ ./test
1
1

Preguntado porMax Fomichev

Respuestas:


ECMAScript (la sintaxis de expresiones regulares predeterminada) intenta hacer coincidir las alternativas en orden, deteniéndose en el primer éxito, lo que significa que en la búsqueda ordinaria (a la regex_search ) la expresión regular a|ab nunca coincide con el ab completo; siempre coincide solo con el a parte.


El estándar era ambiguo sobre lo que regex_match se suponía que debía hacer en este caso, lo que llevó a una divergencia en la implementación. Consulte el número 2273 de LWG para conocer las interpretaciones contrapuestas. Finalmente, se modificó el estándar (consulte la resolución de ese problema) para dejar claro que regex_match solo considera posibles coincidencias que coincidan con toda la secuencia de entrada, como deja claro el ejemplo agregado al estándar:


std::regex re("Get|GetValue");
std::cmatch m;
regex_search("GetValue", m, re); // returns true, and m[0] contains "Get"
regex_match ("GetValue", m, re); // returns true, and m[0] contains "GetValue"

El <regex> original Sin embargo, la implementación en libc++ utilizó la otra interpretación y simplemente no se actualizó para que coincidiera con la resolución hasta hace poco. Clang 4.0 ahora imprime 1 1 .


Algunas respuestas de código


std::regex_match("ab", std::regex("(ab|a)")) == true 
std::regex_match("ab", std::regex("(a|ab)")) == false 
$ cat >
test.cpp #include <string>
#include <regex>
#include <iostream>
int main() {
std::cout <<
std::regex_match("ab", std::regex("(a|ab)")) <<
std::endl;
std::cout <<
std::regex_match("ab", std::regex("(ab|a)")) <<
std::endl;
return 0;
} ^C $ clang++ -v Apple LLVM version 8.1.0 (clang-802.0.41) Target: x86_64-apple-darwin16.5.0 Thread model: posix InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin $ clang++ ./test.cpp -o test $ ./test 0 1
$ cat >
test.cpp #include <string>
#include <regex>
#include <iostream>
int main() {
std::cout <<
std::regex_match("ab", std::regex("(a|ab)")) <<
std::endl;
std::cout <<
std::regex_match("ab", std::regex("(ab|a)")) <<
std::endl;
return 0;
} ^C $ clang++ -v FreeBSD clang version 3.8.0 (tags/RELEASE_380/final 262564) (based on LLVM 3.8.0) Target: x86_64-unknown-freebsd11.0 Thread model: posix InstalledDir: /usr/bin $ clang++ ./test.cpp -o test $ ./test 0 1
$ cat >
test.cpp #include <string>
#include <regex>
#include <iostream>
int main() {
std::cout <<
std::regex_match("ab", std::regex("(a|ab)")) <<
std::endl;
std::cout <<
std::regex_match("ab", std::regex("(ab|a)")) <<
std::endl;
return 0;
} ^C $ g++ -v Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Ubuntu 5.4.1-2ubuntu1~16.04' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-5 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 5.4.1 20160904 (Ubuntu 5.4.1-2ubuntu1~16.04) $ g++ -std=gnu++11 ./test.cpp -o test $ ./test 1 1
std::regex re("Get|GetValue");
std::cmatch m;
regex_search("GetValue", m, re);
// returns true, and m[0] contains "Get" regex_match ("GetValue", m, re);
// returns true, and m[0] contains "GetValue"