Problem with boost::find_format_all, boost::regex_finder and custom regex formatter (bug boost 1.42)
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
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;
}
}
精彩评论