请注意,这不是StackOverflow上关于gcc的许多问题的重复,我使用的是Visual Studio 2013。
这个简单的正则表达式构造抛出std::regex_error
:
bool caseInsensitive = true;
char pattern[] = "\bword\b";
std::regex re(pattern, std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : 0));
what
在异常对象上返回的实际错误不一致。通常是一个不匹配的排列或支架。为什么?
问题的出现是因为std::regex
有多个构造函数可用。对构造函数的跟踪显示它使用了一个我不打算使用的构造函数!
我想用这个:
explicit basic_regex(_In_z_ const _Elem *_Ptr,
flag_type _Flags = regex_constants::ECMAScript)
但我得到了这个:
basic_regex(_In_reads_(_Count) const _Elem *_Ptr, size_t _Count,
flag_type _Flags = regex_constants::ECMAScript)
标志中的三元表达式导致类型更改为int
,它不再与构造函数签名中的flag_type
匹配。由于它在size_t
上进行匹配,因此它调用该构造函数。这些标志被误解为字符串的大小,导致在访问超过字符串末尾的内存时出现未定义的行为。
该问题并非Visual Studio特有。我能够在gcc中复制它:http://ideone.com/5DjYiz
它可以通过两种方式进行修复。首先是一个明确的论点:
std::regex re(pattern, static_cast<std::regex::flag_type>(std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : 0)));
第二是避免在三元表达式中使用整数常量:
std::regex re(pattern, caseInsensitive ? std::regex_constants::ECMAScript | std::regex_constants::icase : std::regex_constants::ECMAScript);
我觉得所提出的任何一个解决方案都不是特别引人注目或美观。我想我更喜欢这样的东西:
auto options = std::regex_constants::ECMAScript;
if (caseInsensitive)
options |= std::regex_constants::icase;
std::regex re(pattern, options);
如果出于某种错误的原因,你真的坚持使用一行代码,我会在三元表达式中使用正确类型的值构造对象:
std::regex re(pattern, std::regex_constants::ECMAScript | (caseInsensitive ? std::regex_constants::icase : std::regex_constants::std::regex_option_type{}));
或者,由于ECMAScript是默认的,您可以使用:
std::regex re(pattern, (caseInsensitive ? std::regex_constants::icase : std::regex_constants::ECMAScript));
至少在我看来,第一个显然更可取。