0

所以,我有以下精神业力规则体:

base_rule = 
    eps(_r1 != 0) [ // _r1 is a pointer_typed placeholder
        eps
    ]
;

这导致来自 g++ 的相当长的错误消息(有帮助)以:

/opt/dev_64_swat/Boost/include/boost/spirit/home/phoenix/operator/comparison.hpp
:37:5: error: ISO C++ forbids comparison between pointer and integer 
[-fpermissive]

这是有效的 C++:

struct zebra{};

int main()
{
  zebra * x;
  if( x == 0);  
}

我想尝试boost::phoenix::static_cast_<_r1_type *>(0)转换_r1_type为整数(是的,这是错误的,这只是一个实验)。

问题:

当点为零时,如何使用精神 eps 构造对占位符执行指针测试以防止规则体评估?

与所有“C++ 函数式编程库使用”问题一样,我希望答案让我感觉自己像个傻瓜。

答案

Ildjam 的观点直接回答了我的问题。我的问题有两个问题;上面有个间接问题。这与 PEG 中的条件有关。我想表达的应该这样写:

rule = ( eps(_r) << ( /* grammar for when pointer is not null */ ) ) 
    | eps // otherwise dont do anything.
;

我使用语义动作主体(在 [] 块中指定)来表达语法的条件部分。奇怪的是,虽然我之前写过条件 PEG 语法,但我只是犯了一个错误,导致了第二类问题。

因此, eps(_r1) 可以解决问题,第二种类型的编译问题与问题无关。

4

2 回答 2

3

这是 C++03 中 C++ 类型系统的一个基本问题。0 是特殊的,可以在许多它的typeint、 不能的地方使用。这个问题很容易演示,并在模板和指针结合时导致大量问题。

void f(int i) {
    void* ptr = ...;
    if (ptr == i) { // MALFORMED
    }
}

f(0); // But I'm trying to compare with 0, which is legit!

template<typename T, typename Y> T construct_from(const Y& y) {
    return T(y);
}
construct_from<void*>(0); // ERROR, cannot construct ptr from int.

最简单的解决方案是编写一个快速版本的nullptr,可以在 C++0x 中找到。

struct nullptr_t {
    template<typename T> operator T*() const {
        return 0;
    }
};
于 2011-06-01T16:52:30.657 回答
2

正如我在评论中所建议的那样,使用隐式bool转换指针对我来说是开箱即用的 Boost 1.46.1。以下是一个最小的复制,其中parse成功如果(且仅当)p != 0 && input == "not null"p == 0 && input == "null"

#include <string>
#include <ios>
#include <ostream>
#include <iostream>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace spirit = boost::spirit;
namespace qi = spirit::qi;

struct test_grammar : qi::grammar<std::string::const_iterator, void(int*)>
{
    test_grammar() : base_type(start_)
    {
        start_
            =   (   spirit::eps(spirit::_r1)
                    >> "not null"
                |   spirit::eps(!spirit::_r1)
                    >> "null"
                )
                >> spirit::eoi
            ;
    }

private:
    qi::rule<base_type::iterator_type, base_type::sig_type> start_;
};
test_grammar const test;

int main()
{
    int i = 42;
    int* p = &i;                          // alternatively, = 0;
    std::string const input = "not null"; // alternatively, = "null";

    std::string::const_iterator first = input.begin();
    std::cout
        << std::boolalpha
        << "parse succeeded: "
        << qi::parse(first, input.end(), test(p))
        << std::endl;
}

因此,无论您在尝试以这种方式使用隐式转换时遇到什么问题,它都必须特定于您的代码;即,您必须展示更多代码才能获得任何有用的反馈。

于 2011-06-01T17:14:15.957 回答