views:

86

answers:

1

I have a code that has been working for almost 4 years (since boost 1.33) and today I went from boost 1.36 to boost 1.42 and now I have a problem.

I'm calling a custom formatter on a string to format parts of the string that match a REGEX.

For instance, a string like: "abc;def:" will be changed to "abc\2Cdef\3B" if the REGEX contains "([;:])"

boost::find_format_all( mystring, boost::regex_finder( REGEX ), custom_formatter() );

The custom formatter looks like this:

struct custom_formatter()
{

  template< typename T >
  std::string operator()( const T & s ) const
  {
      std::string matchStr = s.match_results().str(1);

      // perform substitutions

      return matchStr;
  }

}

This worked fine but with boost 1.42 I know have "non initialized" s.match_results() which yield to boost::exception_detail::clone_implINS0_::error_info_injectorISt11logic_errorEEEE - Attempt to access an uninitialzed boost::match_results<> class.

This means that sometimes I am in the functor to format a string but there is no match.

Am I doing something wrong? Or is it normal to enter the functor when there is no match and I should check against something?

for now my solution is to try{}catch(){} the exception and everything works fine, but somehow that doesn't feel very good.

EDIT1

Actually I have a new empty match at the end of each string to parse.

EDIT2 : one solution inspired by ablaeul

  template< typename T >
  std::string operator()( const T & s ) const
  {

      if( s.begin() == s.end() ) return std::string();

      std::string matchStr = s.match_results().str(1);

      // perform substitutions

      return matchStr;
  }

EDIT3 Seems to be a bug in (at least) boost 1.42

+1  A: 

The struct find_regexF seems to be the culprit. As you can see, it returns an empty result with a uninitialized match_results(). Looking through SO found me the following solution:

struct custom_formatter()
{

  template< typename T >
  std::string operator()( const T & s ) const
  {
      std::string matchStr;
      for (typename T::const_iterator i = Match.begin();
             i != Match.end();
             i++) {
          // perform substitutions via *i
      }
      return matchStr;
  }

}

EDIT: Looking at how Boost uses the formatter here is another solution:

template<typename InputIteratorT>
std::string operator()( 
    const regex_search_result<InputIteratorT>& Replace ) const
{
    if ( Replace.empty() )
    {
        return std::string();
    }
    else
    {
        std::string matchStr = s.match_results().str(1);
        // perform substitutions
        return matchStr;      
    }
}
ablaeul
The problem with this is that you don't have regex groups. Each iteration on *i will give you a character but you cannot get for instance the group you wanted (with a more complicated regex I mean).But I can just test s.begin() == s.end() at the beginning and exit if it is the case. But I don't really see why I get empty results.
Nikko
yep I've done something like this, at least for when I use boost version 1.42, waiting for a bug correction. Thanks for the help.
Nikko