Suppose I have a structure that I want to parse into with Spirit Qi, that is defined as such:
struct data_
{
bool export;
std::wstring name;
data_()
How to set a struct member.
phx::bind
)Given a struct S
struct S
{
int field1;
std::string field2;
int target_field;
bool field3;
};
You can assign to a field (e.g. target_field
) like so:
rule p = int_ [ phx::bind(&S::target_field, _val) = _1 ];
Now, you can make the bind
more readable, by doing something like:
auto target_field_ = phx::bind(&S::target_field, _val);
p = int_ [ target_field_ = _1 ];
Proof of concept: live on Coliru
#include "boost/spirit/include/qi.hpp"
#include "boost/spirit/include/phoenix.hpp"
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
typedef std::string::const_iterator It;
struct S
{
int field1;
std::string field2;
int target_field;
bool field3;
};
int main()
{
const std::string input("42");
It f(begin(input)), l(end(input));
S instance;
using namespace qi;
rule p = int_ [ phx::bind(&S::target_field, _val) = _1 ];
// or, alternatively:
auto target_field_ = phx::bind(&S::target_field, _val);
p = int_ [ target_field_ = _1 ];
if (parse(f, l, p, instance))
std::cout << "Parsed: " << instance.target_field;
}
You can treat a struct as a fusion sequence by using adaptation:
#include "boost/fusion/adapted/struct.hpp"
BOOST_FUSION_ADAPT_STRUCT(S, (int, field1)(std::string, field2)(int, target_field)(bool, field3))
Now you can use phoenix lazy functions on these sequences in your semantic action:
rule p = int_ [ phx::at_c<2>(_val) = _1 ];
I don't prefer this style (because it 'degrades' an expressive struct to ... a tuple of sorts), but it might come in handy. Live on Coliru