所以,我有以下精神业力规则体:
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构造对占位符执行指针测试,以防止在点为零时进行规则体评估?
与所有&#34; C ++函数式编程库的使用一样&#34;问题我希望答案让我觉得自己像个傻瓜。
答案
Ildjam的观点直接回答了我的问题。我的问题有两个问题;上面有一个间接的问题。这与PEG中的条件有关。我要表达的内容应该是这样写的:
rule = ( eps(_r) << ( /* grammar for when pointer is not null */ ) )
| eps // otherwise dont do anything.
;
我正在使用语义动作主体(在[]块中指定)来表达语法的条件部分。奇怪的是,我之前写过有条件的PEG语法,我只是犯了一个错误,导致了第二类问题。
因此,eps(_r1)可以解决问题,第二种类型的编译问题与问题无关。
答案 0 :(得分:3)
这是C ++ 03中C ++类型系统的基本问题。 值 0是特殊的,可以在 type ,int
的许多地方使用,但不能。这个问题很容易证明,并且会导致模板和指针结合的大量问题。
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;
}
};
答案 1 :(得分: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;
}
因此,无论您在尝试以这种方式使用隐式转换时遇到什么问题,它都必须特定于您的代码;也就是说,您必须显示更多代码才能获得有用的反馈。