说我有这样的结构:
struct MyStruct
{
int a;
int b;
int c;
}
BOOST_FUSION_ADAPT_STRUCT
(
MyStruct,
(int, a)
(int, b)
(int, c)
)
然后如果我有一个简单的发电机:
struct MyStructGenerator
: boost::spirit::karma::grammar<boost::spirit::ostream_iterator, MyStruct()>
{
MyStructGenerator() : MyStructGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;
start_ = '<'
<< bsk::int_
<< ','
<< bsk::int_
<< ','
<< bsk::int_
<< '>';
}
~MyStructGenerator() = default;
boost::spirit::karma::rule<boost::spirit::ostream_iterator, MyStruct()> start_;
};
我运行以下内容:
int main()
{
MyStruct ms = { 3, 2, 1 };
std::cout << boost::spirit::karma::format(MyStructGenerator(), ms) << std::endl;
}
我当然希望看到<3, 2, 1>
。我无法弄清楚如何改变规则内的顺序?如果我想查看<1, 2, 3>
或即使我想查看<2, 1, 3>
该怎么办?
另外,无论如何我可以在没有BOOST_FUSION_ADAPT_STRUCT
的情况下执行此操作吗?
答案 0 :(得分:3)
只需更改适应的订单:
简化 Live On Wandbox :
<2, 1, 3>
打印#include <boost/fusion/adapted/struct.hpp>
struct MyStruct { int a, b, c; };
BOOST_FUSION_ADAPT_STRUCT(MyStruct, a, b, c)
#include <boost/spirit/include/karma.hpp>
namespace bsk = boost::spirit::karma;
template <typename It = boost::spirit::ostream_iterator>
struct MyGen : bsk::grammar<It, MyStruct()> {
MyGen() : MyGen::base_type(start_) {
using namespace bsk;
start_ = '<' << int_ << ',' << int_ << ',' << int_ << '>';
}
private:
bsk::rule<It, MyStruct()> start_;
};
int main() {
MyGen<> gen;
std::cout << format(gen, MyStruct { 3, 2, 1 }) << "\n";
}
,但
<3,2,1>
打印BOOST_FUSION_ADAPT_STRUCT(MyStruct, c, b, a)
。
好。我可以向您展示一些您可能感兴趣的事情:
: Live On Wandbox :
<1,2,3>
打印
#include <boost/fusion/adapted/struct.hpp>
struct MyStruct { int a, b, c; };
BOOST_FUSION_ADAPT_STRUCT(MyStruct, c, b, a)
#include <iostream>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/as_vector.hpp>
using boost::fusion::as_vector;
int main() {
MyStruct ms { 3, 2, 1 };
std::cout << as_vector(ms) << "\n";
std::cout
<< boost::fusion::tuple_open("<")
<< boost::fusion::tuple_delimiter(",")
<< boost::fusion::tuple_close(">");
std::cout << as_vector(ms) << "\n";
}
命名改编:您可以使用(1 2 3)
<1,2,3>
宏同时调整的不同订单。这是一个使用Fusion IO和Karma生成器演示的演示。
注意我稍微修改了结构,因此更容易跟踪哪个字段为
*_NAMED
,'a'
或'b'
。
查看 Live On Wandbox :
'c'
打印
#include <boost/fusion/adapted/struct.hpp>
struct MyStruct { char a, b, c; };
BOOST_FUSION_ADAPT_STRUCT_NAMED(MyStruct, AsABC, a, b, c)
BOOST_FUSION_ADAPT_STRUCT_NAMED(MyStruct, AsBCA, b, c, a)
BOOST_FUSION_ADAPT_STRUCT_NAMED(MyStruct, AsCBA, c, b, a)
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/qi.hpp>
namespace bsk = boost::spirit::karma;
template <typename Attr, typename It = boost::spirit::ostream_iterator>
struct MyGen : bsk::grammar<It, Attr()> {
MyGen() : MyGen::base_type(start_) {
using namespace bsk;
start_ = '<' << auto_ << ',' << auto_ << ',' << auto_ << '>';
}
private:
bsk::rule<It, Attr()> start_;
};
#include <iostream>
#include <boost/fusion/include/io.hpp>
#include <boost/fusion/include/as_vector.hpp>
using boost::fusion::as_vector;
template <typename Attr>
void do_tests(Attr const& ms) {
std::cout << as_vector(ms) << "\n";
std::cout << format(MyGen<Attr>{}, ms) << "\n";
}
int main() {
std::cout << boost::fusion::tuple_open("<") << boost::fusion::tuple_delimiter(",") << boost::fusion::tuple_close(">");
MyStruct ms { 'a', 'b', 'c' };
using namespace boost::fusion::adapted;
do_tests(AsABC{ms});
do_tests(AsCBA{ms});
do_tests(AsBCA{ms});
}
是的,你可以不做适应(不要):
Live On Wandbox (由于编译时限制而评论部分)
<a,b,c>
<a,b,c>
<c,b,a>
<c,b,a>
<b,c,a>
<b,c,a>
打印
struct MyStruct { char a, b, c; };
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace bsk = boost::spirit::karma;
namespace phx = boost::phoenix;
template <typename It = boost::spirit::ostream_iterator>
struct MyGen : bsk::grammar<It, MyStruct()> {
MyGen() : MyGen::base_type(start_) {
using boost::proto::deep_copy;
using namespace bsk;
auto A = deep_copy(char_[ _1 = phx::bind(&MyStruct::a, _val) ]);
auto B = deep_copy(char_[ _1 = phx::bind(&MyStruct::b, _val) ]);
auto C = deep_copy(char_[ _1 = phx::bind(&MyStruct::c, _val) ]);
start_ =
'<' << A << ',' << B << ',' << C << '>' << eol <<
'<' << A << ',' << C << ',' << B << '>' << eol <<
'<' << B << ',' << A << ',' << C << '>' << eol <<
'<' << C << ',' << A << ',' << B << '>' << eol <<
'<' << B << ',' << C << ',' << A << '>' << eol <<
'<' << C << ',' << B << ',' << A << '>' << eol
;
}
private:
bsk::rule<It, MyStruct()> start_;
};
int main() {
std::cout << format(MyGen<>{}, MyStruct { 'a', 'b', 'c' });
}
答案 1 :(得分:2)
您可以简单地使用phoenix和bind来访问成员值。 因此,对于您交换成员的示例,它将是这样的:
#include <iostream>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/phoenix/bind/bind_member_variable.hpp>
using namespace std;
struct MyStruct {
int a;
int b;
int c;
};
struct MyStructGenerator : boost::spirit::karma::grammar<boost::spirit::ostream_iterator, MyStruct()>
{
MyStructGenerator() : MyStructGenerator::base_type(start_)
{
namespace bsk = boost::spirit::karma;
start_ = '<'
<< bsk::int_[bsk::_1 = boost::phoenix::bind(&MyStruct::c, bsk::_val)]
<< ','
<< bsk::int_[bsk::_1 = boost::phoenix::bind(&MyStruct::b, bsk::_val)]
<< ','
<< bsk::int_[bsk::_1 = boost::phoenix::bind(&MyStruct::a, bsk::_val)]
<< '>';
}
~MyStructGenerator() = default;
boost::spirit::karma::rule<boost::spirit::ostream_iterator, MyStruct()> start_;
};
int main() {
MyStruct ms = { 3, 2, 1 };
std::cout << boost::spirit::karma::format(MyStructGenerator(), ms) << std::endl;
}