Is gcc 4.8 or earlier buggy about regular expressions?

前端 未结 3 1773
一向
一向 2020-11-21 04:29

I am trying to use std::regex in a C++11 piece of code, but it appears that the support is a bit buggy. An example:

#include 
#include 

        
3条回答
  •  情歌与酒
    2020-11-21 05:16

    Feature Detection

    This is a snippet to detect if the libstdc++ implementation is implemented with C preprocessor defines:

    #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 is defined in bits/regex.tcc in 4.9.x
    • _GLIBCXX_REGEX_STATE_LIMIT is defined in bits/regex_automatron.h in 5+
    • _GLIBCXX_RELEASE was added to 7+ as a result of this answer and is the GCC major version

    Testing

    You can test it with GCC like this:

    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
    

    Results

    Here are some results for various compilers:


    $ 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
    

    Here be Dragons

    This is totally unsupported and relies on the detection of private macros that the GCC developers have put into the bits/regex* headers. They could change and go away at anytime. Hopefully, they won't be removed in the current 4.9.x, 5.x, 6.x releases but they could go away in the 7.x releases.

    If the GCC developers added a #define _GLIBCXX_HAVE_WORKING_REGEX 1 (or something, hint hint nudge nudge) in the 7.x release that persisted, this snippet could be updated to include that and later GCC releases would work with the snippet above.

    As far as I know, all other compilers have a working when __cplusplus >= 201103L but YMMV.

    Obviously this would completely break if someone defined the _GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT or _GLIBCXX_REGEX_STATE_LIMIT macros outside of the stdc++-v3 headers.

提交回复
热议问题