我正在使用业力来生成大型结构的表示,但结构在生成期间被复制.我不认为他们需要,所以想知道如何避免它.
下面的快速示例打印"Copy!",因为目标结构被复制到rule::generate:
namespace karma = spirit::karma;
namespace phoenix = boost::phoenix;
struct foo
{
foo() { }
foo( foo const &other ) { std::cout << "Copy!"; }
int f() const { return 42; }
};
std::string output;
typedef std::back_insert_iterator< std::string > iterator;
karma::rule< iterator, foo() > foo_rule =
karma::int_[ karma::_1 = phoenix::bind( &foo::f, karma::_val ) ];
foo my_foo;
iterator it( output );
karma::generate( it, foo_rule, my_foo );
Run Code Online (Sandbox Code Playgroud)
我可以foo_rule通过引用声明属性来停止复制:
karma::rule< iterator, foo &() > …Run Code Online (Sandbox Code Playgroud) 我在使用karma为boost :: shared_ptrs的向量中保存的结构生成输出时遇到了一些麻烦.我有一个使用不能编译的int的小测试用例.我以为我可以使用deref_iterator自定义点来处理这种情况,或者也许开箱即用的精神会注意到我的容器持有指针类型并进行额外的解引用.无论如何,这是测试用例:
#include <boost/spirit/include/karma.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
typedef boost::shared_ptr< int > ptr;
typedef std::vector< ptr > vec;
namespace boost {
namespace spirit {
namespace traits {
// specialise how iterators into containers of pointers are dereferenced
template <>
struct deref_iterator< typename container_iterator< vec const >::type >
{
typedef int type;
static
type
call( typename container_iterator< vec const >::type & it ) {
return **it;
}
};
} // namespace traits
} // namespace spirit
} // namespace boost …Run Code Online (Sandbox Code Playgroud) 我看到一个错误,我没有看到解决方案.一,相关代码:
namespace C {
struct RangeEntry {
size_t byte;
boost::optional<size_t> bit;
};
struct Range {
RangeEntry firstPart;
boost::optional<RangeEntry> secondPart;
boost::optional<size_t> shift;
};
}
BOOST_FUSION_ADAPT_STRUCT(
C::RangeEntry,
(size_t, byte)
(boost::optional<size_t>, bit)
)
BOOST_FUSION_ADAPT_STRUCT(
C::Range,
(C::RangeEntry , firstPart)
(boost::optional<C::RangeEntry> , secondPart)
(boost::optional<size_t> , shift)
)
... Declare the rules ...
karma::rule<Iterator, C::Range()> range;
karma::rule<Iterator, C::RangeEntry()> range_part;
... Define rules ...
range_part %= no_delimit[ulong_ << -(lit(":") << ulong_)];
range %= no_delimit[range_part << -(lit("-") << range_part)] << -(lit("<<") << ulong_);
Run Code Online (Sandbox Code Playgroud)
在该range %=部分,我得到编译错误
/usr/include/boost/spirit/home/karma/numeric/detail/numeric_utils.hpp:504:30: …Run Code Online (Sandbox Code Playgroud) 我想生成一些格式化的输出.为此,需要一些缩进.因此,在生成期间的某个时刻,我希望获得当前位置,以便使用该数量缩进以下行.
这是一个最小的例子.请假设,我们不知道karma::lit("Some text: ")编译期间的输出有多长.实际上,这个前导文本可能由几个规则生成.
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
#include <boost/spirit/include/karma.hpp>
using namespace std;
int main() {
vector<int> v { 0, 1, 2, 3 };
{
namespace karma = boost::spirit::karma;
karma::rule<ostream_iterator<char>, std::vector<int>() > myRule =
karma::lit("Some text: ") << (karma::int_ % karma::eol);
karma::generate(ostream_iterator<char>(cout), myRule, v);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这产生了
Some text: 0
1
2
3
Run Code Online (Sandbox Code Playgroud)
我想结果:
Some text: 0
1
2
3
Run Code Online (Sandbox Code Playgroud)
要实现这一点,需要在生成向量之前知道当前位置.那么,类似的东西qi::raw[]呢?
更新:指向此点生成输出的指针也可以.
我有一个Qi语法定义,用于解析输入。后来我有了一个Karma生成器,其输出方式应该与输入类似。
这有可能吗?解析器语法似乎可以自动转换为生成器语法(??)。
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <iostream>
int main(){
//test input
std::string s = "Xx 1.233 pseudo";
//input variables
std::string element;
double mass;
std::string pseudo;
auto GRAMMAR =
boost::spirit::qi::lexeme[+(boost::spirit::qi::char_ - ' ' - '\n')]
>> boost::spirit::qi::double_
>> boost::spirit::qi::lexeme[+(boost::spirit::qi::char_ - ' ' - '\n')];
bool r = boost::spirit::qi::phrase_parse(
s.begin(), s.end(),
GRAMMAR,
boost::spirit::qi::space, element, mass, pseudo
);
std::cout << boost::spirit::karma::format(
GRAMMAR ??? is it possible?
,
element,
mass,
pseudo
);
}
Run Code Online (Sandbox Code Playgroud)