[Regex] regex_match() and substr()

Hi, It seem that there is a problem when using the substr function in regex_match(). If you build and run the following code, it works fine. But try to comment the 6th line in findC function and uncomment the 7th line. Under Visual C++ 2005, I get the following: Debug assertion failed! Program: ..........exe File: ..........\vc\include\xstring Line: 271 Expression: string iterators incompatible Did I miss something? Thanks Eric // main.cpp #include <string> #include <iostream> #include <boost/regex.hpp> bool findC(const std::string& iText) { boost::regex regularExp(".*C.*"); boost::smatch match; std::string sub( iText.substr(2) ); if ( boost::regex_match(sub, match, regularExp) ) //if ( boost::regex_match(iText.substr(2), match, regularExp) ) { for ( int i=0; i<match.size(); ++i ) { if (match[i].matched) { std::cout << "match[" << i << "] " << match[i] << std::endl; return true; } } } else { std::cout << "'C' not found in '" << iText.substr(2) << "'" << std::endl; return false; } } int main( int argc, char* argv[] ) { //findC("x:ABXDE"); findC("x:ABCDE"); return EXIT_SUCCESS; }

capourrait@free.fr wrote:
Hi,
It seem that there is a problem when using the substr function in regex_match(). If you build and run the following code, it works fine. But try to comment the 6th line in findC function and uncomment the 7th line. Under Visual C++ 2005, I get the following: Debug assertion failed! Program: ..........exe File: ..........\vc\include\xstring Line: 271 Expression: string iterators incompatible
Did I miss something?
Yes: substring() returns a *temporary* string object, by the time that regex_match returns the string it has searched has gone out of scope and been destroyed, so all the iterators stored in the match are now invalid. If you want to search a substring then you must assign the string to an object before calling regex_match. But better, use the iterators directly: if ( boost::regex_match(iText.begin()+2, iText.end(), match, regularExp) ) HTH, John.

John Maddock wrote:
capourrait@free.fr wrote:
Hi,
It seem that there is a problem when using the substr function in regex_match().
Yes: substring() returns a *temporary* string object, by the time that regex_match returns the string it has searched has gone out of scope and been destroyed, so all the iterators stored in the match are now invalid.
<snip> I recently discovered something new (to me) about rvalues and const volatile references. It seems an rvalue will not bind to one. This property can be used to prevent misuses such as the one above. Consider the following: #include <string> template<typename T> void foo( T const volatile & t) { } std::string volatile bar() { return std::string(""); } int main() { std::string str(""); std::string const cstr(""); foo(str); // works foo(cstr); // works //foo(str.substr(2)); // doesn't work //foo(bar()); // doesn't work return 0; } To solve John's problem, regex_match() can be defined to take a "std::string const volatile &", and then it merely casts the volatile away inside. (The foo(bar()) case serves to demonstrate that this trick cannot be fooled by volatile-qualified rvalues, because std::string doesn't have a volatile copy constructor -- and in practice, no types do.) (Note: this doesn't work on any msvc compilers, which will happily bind temporaries to const volatile references.) It seems to me this property should also be usable to (finally!) solve the problem of detecting the lvalue/rvalue-ness of an expression at compile time, which would let us emulate decltype in C++03. But I have yet to find a formulation that Comeau Online accepts. Perhaps I'll need to refer to the standard. -- Eric Niebler Boost Consulting www.boost-consulting.com

Eric Niebler wrote:
I recently discovered something new (to me) about rvalues and const volatile references. It seems an rvalue will not bind to one. This property can be used to prevent misuses such as the one above.
New to me too.
To solve John's problem, regex_match() can be defined to take a "std::string const volatile &", and then it merely casts the volatile away inside.
Yikes a const_cast.
(Note: this doesn't work on any msvc compilers, which will happily bind temporaries to const volatile references.)
:-( I don't suppose that there is any way to poison the existing overloads with functions that *only* bind to rvalues? Just checking :-) Thanks, John.
participants (3)
-
capourraitīŧ free.fr
-
Eric Niebler
-
John Maddock