C++ <;regex>;std::regex相当于Qt';s QRegularExpression::isValid()不触发异常

C++ <;regex>;std::regex相当于Qt';s QRegularExpression::isValid()不触发异常,c++,regex,exception-handling,std,c++17,C++,Regex,Exception Handling,Std,C++17,我正在尝试将一些正则表达式工具从Qt迁移到std。在Qt中,我可以在将正则表达式与一起使用之前测试它是否有效 在std的中,我看不到这样做的方法。所以现在,我有try/catch块,它使用用户提供的正则表达式生成正则表达式,然后尝试将其与一个1字符字符串进行匹配,以快速触发std::regex_错误异常,而不加载实际的搜索字符串,因此我可以提前退出。在我看来,这是一个肮脏的黑客行为,但我不确定是否有更好的方法可以使用std::regex有效地测试它们。我基本上是在使用该工具的自动输入时,通过捕获

我正在尝试将一些正则表达式工具从Qt迁移到std。在Qt中,我可以在将正则表达式与一起使用之前测试它是否有效

在std的
中,我看不到这样做的方法。所以现在,我有
try/catch
块,它使用用户提供的正则表达式生成正则表达式,然后尝试将其与一个1字符字符串进行匹配,以快速触发
std::regex_错误
异常,而不加载实际的搜索字符串,因此我可以提前退出。在我看来,这是一个肮脏的黑客行为,但我不确定是否有更好的方法可以使用
std::regex
有效地测试它们。我基本上是在使用该工具的自动输入时,通过捕获和处理异常来避免性能问题

try
{
    const std::regex regex_exception_trigger(regex_string);
    std::smatch stability_match;
    const std::string test_string = "0";
    if (std::regex_search(test_string.begin(), test_string.end(), stability_match, regex_exception_trigger)) {}
}
catch (std::regex_error &re) { std::cerr << re.what() << std::endl; print_help(); return exit_enum::BAD_REGEX;  }
试试看
{
常量std::正则表达式正则表达式异常触发器(正则表达式字符串);
std::smatch稳定性\匹配;
常量std::字符串测试\u string=“0”;
if(std::regex_搜索(test_string.begin()、test_string.end()、稳定性_匹配、regex_异常_触发器)){
}
catch(std::regex_error&re){std::cerrC++库(尤其是标准库)通常遵循这样一种理念,即如果您有一个类的实例,那么该实例就是有效的。因此,如果您试图用错误的输入构造一个类,它将在您构造它时抛出异常,而不是在您尝试使用它时抛出异常

这通常是好的,因为它清楚地表明了错误的地方:如果我试图用一个构造错误的正则表达式解析一个字符串,我得到一个异常,那么自然的想法是字符串有问题,而不是正则表达式

您的用例不适合这个模型,因为C++标准库假定构造不良的正则表达式是例外的(因此例外)。 当不抛出异常时,异常是便宜的(即,如果不需要捕获任何内容,那么

try-catch
块的开销很小),但实际上捕获异常可能代价高昂。如果您希望收到大量构造不正确的正则表达式,并且您认为捕获异常会显著影响性能(尽管捕获异常的代价很高,但您仍然可以,因此您应该做一些测试)在构造正则表达式之前,您需要考虑一个不同的工具。


Boost还提供了一个标准库版本所基于的正则表达式库。语法将非常相似。Boost的版本有一个标志,可以传递给正则表达式构造函数,并将抑制无效字符串的任何异常。我上面给出的原因可能是标准库中没有包含该标志的原因如果你需要这个行为,你可以考虑使用Boost版本。< /P> < P>如果你想捕捉所有的错误,在尝试{{}} catch {} catch {} catch {}序列}。 我把建筑和使用分开

伪码

std::regex Rx;
bool bIsConstructError = false;

////////////////////////////////////////
bool SetRx( std::string& strRx )
{
   bIsConstructError = false;
   try 
   {
      Rx.assign( "", 0);
      Rx.assign( strRx, 0 );
   }
   catch ( std::regex_error & e )
   {
      bIsConstructError = true;
      return false;
   }
   catch ( std::out_of_range & e )
   {
      bIsConstructError = true;
      return false;
   }
   catch ( std::runtime_error & e )
   {
      bIsConstructError = true;
      return false;
   }
   return true;
}

////////////////////////////////////////
bool  findText( std::string& strTarget )
{
   if ( bIsConstructError )
      return false;

   bool bRet = true;

   std::smatch _M;
   std::string::const_iterator start = strTarget.begin();
   std::string::const_iterator end = strTarget.end();

   try
   {
      if ( regex_search( start, end, _M, Rx, 0 ) )
      {
          // do something
      }
   }
   catch ( std::out_of_range & e )
   {
      bRet = false;
   }
   catch ( std::runtime_error & e )
   {
      bRet = false;
   }
   return bRet;
}

在我的测试中,它没有测试正则表达式。如果它的格式不正确,它会在构造函数中抛出一个异常。如果你有用户定义的表达式,你应该将构造从使用函数中分离出来。这为知道构造失败与使用函数抛出之间的关系提供了一些余地。我只做了一个全局设置,然后分配正则表达式在用户输入上。这使得它更容易。我只看到C++尝试/ catch块捕获一些东西,比如“代码> catch(STD::ExabutyNo.E))/>代码,或者捕捉可能的一切,以捕获<代码> catch(…)>代码>我会做,<代码>尝试{} catch {} /Cuth>?或者,您是指catch(…)是否会因为未指定要捕获的异常而绕过性能影响?我正在尝试避免在捕获中处理它们的性能影响。我只希望我的应用程序在出现错误正则表达式时立即优雅地关闭,而不是对异常执行任何操作。我的应用程序没有遇到性能影响,这是什么意思?我不明白你如何保护它们另外,当你的应用程序刚锁起来时,你就变得盲目了。BTW,只需要一个我所列的catch语句。而且,这些正则表达式函数在抛出之前都解压缩了堆栈,并且不会降低内存。很可能我在读C++异常处理时感到困惑。ce命中仅在抛出时发生,如果此答案正确:|如果是这样,此答案很好地分解了所有可能的异常以进行处理。您使用regex库,并且允许用户输入regex。仅出于此原因,您应该使用try/catch。不用于任何内部用途。在构造和使用时,如果如果出现这种情况,应用程序可能会停止运行,不会让您有机会看到它是什么,也不会给用户另一个机会。让您的应用程序无缘无故退出看起来也不太好。很可能是语法错误,但其他时候可能是太复杂的错误或堆栈错误。