std::regex构造函数抛出异常。

10
请注意,这与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 方法返回的异常信息不够一致。通常情况下,它会提示括号或花括号不匹配。为什么会这样呢?

2个回答

12

问题出在 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)
在flags中的三元表达式会导致类型变为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);

8

我认为两种提出的解决方案都不是特别令人信服或美观。我想我更喜欢这样的东西:

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));

至少在我看来,第一个显然更可取。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接