c++regexc++11guideline-support-library

gsl::span fails to compile with std::regex


I'm trying to use gsl::span to pass some data from a packed structure of mixed binary/ascii data (hence no vector or string) to a function, where I want to operate on it with a regex, but I get the following errors:

error C2784: 'bool std::regex_match(_BidIt,_BidIt,std::match_results<_BidIt,_Alloc> &,const std::basic_regex<_Elem,_RxTraits> &,std::regex_constants::match_flag_type)' : could not deduce template argument for 'std::match_results>,_Alloc> &' from 'std::cmatch'

see declaration of 'std::regex_match'

Here's what I'm trying to do:

#include <regex>
#include "gsl.h"

using namespace std;
using namespace gsl;

int main(int argc, const char **argv) 
{
    char lat[8] = { '0', '1', '9', '0', '0', '0', '0', 'E' };
    span<char> s = lat;

    // in a complex implementation this would be in a function,
    // hence the desire for span<>
    std::cmatch match;
    std::regex_match(s.begin(), s.end(), match, std::regex("[0-9]+"));
}

Solution

  • The problem is that std::regex_match cannot resolve the function overload when the iterator type is gsl::continuous_span_iterator because std::cmatch uses a const char* as the iterator type. Neither std::smatch or std::cmatch is appropriate in this case, you need your own std::match_results type. Here's how it should be done:

    #include <regex>
    #include "gsl.h"
    
    using namespace std;
    using namespace gsl;
    
    int main(int argc, const char **argv) 
    {
        char lat[8] = { '0', '1', '9', '0', '0', '0', '0', 'E' };
        span<char> s = lat;
        std::match_results<decltype(s)::iterator> match;
        std::regex_match(s.begin(), s.end(), match, std::regex(".*"));
    }
    

    That said, at the time of this writing, the revised iterator approach still won't compile due to issue #271.

    Until that's fixed, another workaround is:

    int main(int argc, const char **argv) 
    {
        char lat[8] = { '0', '1', '9', '0', '0', '0', '0', 'E' };
        span<char> s = lat;
        std::cmatch match;
        std::regex_match(&s[0], &s[s.length_bytes()], match, std::regex(".*"));
    }
    

    The workaround approach cover cases where spans of the same or different extents are passed to the function.