2013-05-17 6 views
2

Item 개체 목록이 포함 된 ItemList에서 생성자의 Item 개체에 액세스하려면 어떻게해야합니까?boost :: spirit :: karma에서 중첩 된 객체의 데이터에 액세스하는 방법?

다음 샘플 코드는 VC9 (부스트 포함 및 링크 디렉토리가 적절하게 설정되어 있음)에서 컴파일됩니다. 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; 
} 

출력은 다음과 같습니다 당신은 karma::_val를 사용해야합니다

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

답변

3

. 예를 들어 몇 가지 바인더를 쓸 수 있습니다 (간단한 예)

<< 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'을 invlolve 할 것이라고 이미 생각했다. 그러나 나는 그것을 bind하는 것을 생각해 내지 않았다. 이제는 모두 명백해 보인다. – foraidt