2

我刚开始使用 Boost::xpressive 并发现它是一个很棒的库...我浏览了文档并尝试使用 ! 运算符(零或一),但它不编译(VS2008)。

我想匹配一个可能以“sip:”开头也可能不以“sip:”开头的 sip 地址

#include <iostream>
#include <boost/xpressive/xpressive.hpp>

using namespace boost::xpressive;
using namespace std;
int main()
{


    sregex re = !"sip:" >> *(_w | '.') >> '@' >> *(_w | '.');

    smatch what;
    for(;;)
    {
        string input;
        cin >> input;

        if(regex_match(input, what, re))
        {
            cout << "match!\n";
        }
    }

    return 0;
}`
4

2 回答 2

8

您刚刚遇到了困扰大多数 DSEL 的错误。

问题是您希望调用特定的运算符,该运算符实际上是用您的特定语言定义的。然而这个操作符在 C++ 中已经存在,因此查找和重载解析的正常规则适用。

正确运算符的选择是通过 ADL(Argument Dependent Lookup)完成的,这意味着运算符应用的至少一个对象应该是 DSEL 本身的一部分。

例如,考虑这个简单的代码片段:

namespace dsel
{
  class MyObject;
  class MyStream;
  MyStream operator<<(std::ostream&, MyObject);
}

int main(int, char*[])
{
  std::cout << MyObject() << "other things here";
}

因为表达式是从左到右计算的,所以 dsel 的存在dsel::MyObject是病毒性的,即 dsel 将在此处传播。

关于Xpressive,大多数情况下它之所以有效,是因为您使用了特殊的“标记”,Xpressive例如 ( ) 之类的类型实例,_w或者因为病毒效应(例如,“@”有效,因为左侧的表达式>>Xpressive相关的)。

您是否使用:

sregex re = "sip:" >> *(_w | '.') >> '@' >> *(_w | '.');
            ^^^^^^ ~~ ^^^^^^^^^^^
            Regular    Xpressive

Xpressive它会起作用,因为由于运算符的优先规则,右侧的参数被“污染”了。

然而,这里operator!有最高优先级之一。因此,其范围仅限于:

`!"sip:"`

并且由于"sip:"is 的类型char const[5],它只是调用正则,该正operator!则将正确地断定它应用的表达式 istrue并因此评估为boolvalue false

通过 using as_xpr,您可以将 C 字符串转换为Xpressive对象,从而将命名空间中的权利operator!纳入Xpressive考虑范围,并适当地启动重载决议。

于 2010-09-14T14:43:29.010 回答
1

as_xpr helper must be used...

!as_xpr("sip:")
于 2010-09-14T12:25:22.777 回答