在语法构造函数中评估的语义操作(或不评估?
Semantic action evaluated in grammar constructor (or not?)
我一直在学习boost::spirit,并遇到了在语法构建过程中评估语义动作的困惑。以下代码生成输出:
string=
我的假设是,此输出作为附加到orule
的语义操作的一部分。
有没有办法避免这种行为? 或者如果我在语义操作中使用std::cout
,我需要忍受它吗?
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <iostream>
#include <string>
namespace phx = boost::phoenix;
namespace qi = boost::spirit::qi;
template <typename Iterator>
struct my_grammar : qi::grammar<Iterator, std::string( ) >
{
my_grammar() : my_grammar::base_type(orule)
{
using qi::_1;
using qi::_2;
using qi::attr;
using qi::string;
using phx::val;
orule = string("abc") [ std::cout << "string=" << _1 << std::endl ];
}
qi::rule< Iterator, std::string() > orule;
};
int main()
{
typedef std::string::const_iterator iterator_type;
typedef my_grammar<iterator_type> parser;
parser my_parser; // Our grammar
return 0;
}
简短回答:否,在规则初始化期间不评估语义操作。
但是,您的问题是您没有(只是)编写语义操作。
是的,在您的情况下,该表达式的第一部分
std::cout << "string=" << _1 << std::endl
有一个副作用:(std::cout << "string=")
将文本插入到标准 ostream 对象中,然后通过引用返回std::cout
。
这是因为您使用标准库中定义的std::operator<<
,而不是 boost::phoenix::....::operator<<
¹。
您可以通过强制第二个参数的类型为将选择正确重载的类型来解决此问题:
std::cout << phx::val("string=") << _1 << std::endl
当然,您总是可以通过例如
phx::ref(std::cout) << _1 << std::endl
但你会注意到,只要有可能,人们就会跳过这个。正在boost::spirit::_1
的第二个操作数已经诱导了表达式模板上下文(即选择构造惰性参与者而不是副作用的非标准运算符重载)。
¹ 无论如何,最终可能只是boost::proto::....::operator<<
,但这些都是美味的实现细节:)
相关文章:
- 为什么在popback()操作之后,它仍然打印完整的矢量
- std::condition_variable::wait()如何评估给定的谓词
- 重载操作程序时出错>>用于类中的字符串 memebr
- 对字符串进行位操作
- 我可以在 C++ 中的函数体之外进行操作吗?
- MPI突然停止了对多个核心的操作
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- c++11评估顺序(未定义的行为)
- 对字符数组中的元素执行逐位操作
- 如何在directx/c++中进行平移/缩放操作
- 逐位操作的隐式类型转换
- 为什么一个向量上的多线程操作很慢
- 排序时无法执行交换操作.我做的时候它会崩溃.为什么
- 位移操作和位掩码未检测到重复字符
- 如何进行特定的位操作?
- 当我们进行一些操作时,应该使用什么'std::string'或'std::stringstream'?
- 是在编译时评估的C 文字中的算术操作
- 对同一对象进行评估的链接操作和顺序
- 如何使用中间规则操作在野牛中创建短路评估
- 在语法构造函数中评估的语义操作(或不评估?