2013-05-17 45 views
2

在包含Item对象列表的ItemList中,如何访问生成器中的Item对象?如何在boost :: spirit :: karma中访问嵌套对象的数据?

下面的示例代码在VC9上编译(具有适当的boost包含和链接目录设置)。 我不知道如何设置list_generator::item

#include <boost/config/warning_disable.hpp> 

#include <boost/foreach.hpp> 
#include <boost/assign/list_of.hpp> 
#include <boost/range/adaptors.hpp> 
#include <boost/range/algorithm.hpp> 

#include <boost/spirit/include/qi.hpp> 
#include <boost/spirit/include/karma.hpp> 
#include <boost/spirit/include/phoenix.hpp> 

#include <iostream> 
#include <string> 
#include <list> 

namespace karma = boost::spirit::karma; 
namespace spirit = boost::spirit; 
namespace ascii = boost::spirit::ascii; 
namespace phoenix = boost::phoenix; 


class Item 
{ 
public: 
    typedef std::vector<int> Values; 

    Item(const std::string & i, const Values & v) : m_id(i), m_values(v) {} 
    std::string getId() const { return m_id; } 
    const Values & getValues() const { return m_values; } 

private: 
    std::string m_id; 
    Values m_values; 
}; 

class ItemList 
{ 
public: 
    typedef std::map<std::string, Item> Items; 

    ItemList() {} 
    ItemList(const Items & s, const Items & o) : m_some(s), m_other(o) {} 
    const Items getSome() const { return m_some; } 
    const Items getOther() const { return m_other; } 

private: 
    Items m_some;; 
    Items m_other; 
}; 

template <typename Iterator> 
struct list_generator : karma::grammar<Iterator, ItemList()> 
{ 
    list_generator(const ItemList & i) : list_generator::base_type(start) 
{ 
    using karma::int_; 
    using karma::_1; 
    using karma::lit; 

    // Convert maps into lists containing only the values 
    typedef std::vector<Item> Cells; 
    const Cells some = boost::copy_range<Cells>(i.getSome() | boost::adaptors::map_values); 
    const Cells other = boost::copy_range<Cells>(i.getOther() | boost::adaptors::map_values); 

    item = 
     lit("<item>") 
     << lit("<id>")  /*<< lit[_1 = ??.getId()]*/ << lit("</id>") // Item ID 
     << lit("<values>") /*<< (int_ % ';')[_1 = ??.getValues()]*/ << lit("</values>") // List of Item values 
     << lit("</item>"); 

    start = 
     lit("<some>")  << (*item)[_1 = some] << lit("</some>") 
     << lit("<other>") << (*item)[_1 = other] << lit("</other>"); 
} 

karma::rule<Iterator, Item()> item; 
karma::rule<Iterator, ItemList()> start; 
}; 

int main() 
{ 
    const Item::Values values = boost::assign::list_of(1)(2)(3); 
    const Item a("a", values); 
    const Item b("b", values); 

    ItemList::Items some, other; 
    some.insert(std::make_pair(a.getId(), a)); 
    other.insert(std::make_pair(b.getId(), b)); 
    const ItemList items(some, other); 

    typedef std::back_insert_iterator<std::string> Iter; 
    typedef list_generator<Iter> Generator; 

    Generator grammar(items); 

    std::string generated; 
    Iter sink(generated); 
    if (!karma::generate(sink, grammar)) 
    { 
     std::cout << "Generating failed\n"; 
    } 
    else 
    { 
     std::cout << "Generated: " << generated << "\n"; 
    } 

    return 0; 
} 

输出是:

Generated: <some><item><id></id><values></values></item></some><other><item><id></id><values></values></item></other> 

回答

3

您应该使用karma::_val。例如,你可以写一些粘合剂(简单的例子)

<< lit("<id>") 
<< karma::string[_1 = phoenix::bind(&Item::getId, karma::_val)] 
<< lit("</id>") // Item ID 
<< lit("<values>") 
<< (int_ % ';')[_1 = phoenix::bind(&Item::getValues, karma::_val)] 
<< lit("</values>") // List of Item values 
+0

谢谢;那就是诀窍!我已经怀疑这会牵扯到'_val',但我没有想出'绑定'这件事......现在看来这一切都很明显。 – foraidt