views:

48

answers:

2

I just started using Boost::xpressive and find it an excellent library... I went through the documentation and tried to use the ! operator (zero or one) but it doesn't compile (VS2008).

I want to match a sip address which may or may not start with "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;
}`
+1  A: 

as_xpr helper must be used...

!as_xpr("sip:")
rusbi
+5  A: 

You just encountered a bug that plagues most of the DSEL.

The issue is that you want a specific operator to be called, the one actually defined in your specific languages. However this operator already exist in C++, and therefore the normal rules of Lookup and Overload resolution apply.

The selection of the right operator is done with ADL (Argument Dependent Lookup), which means that at least one of the objects on which the operator apply should be part of the DSEL itself.

For example, consider this simple code snippet:

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

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

Because the expression is evaluated from left to right, the presence of dsel::MyObject is viral, ie the dsel will here be propagated.

Regarding Xpressive, most of the times it works because you use special "markers" that are Xpressive type instances like (_w) or because of the viral effect (for example "@" works because the expression on the left of >> is Xpressive-related).

Were you to use:

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

It would work, because the right hand-side argument is "contaminated" by Xpressive thanks to the precedence rules of the operators.

However here operator! has one of the highest precedence. At such, its scope is restricted to:

`!"sip:"`

And since "sip:" is of type char const[5], it just invokes the regular operator! which will rightly conclude that the expression to which it applies is true and thus evaluate to the bool value false.

By using as_xpr, you convert the C-string into an Xpressive object, and thus bring in the right operator! from the Xpressive namespace into consideration, and overload resolution kicks in appropriately.

Matthieu M.
Great answer! Thank you.
rusbi