나는 다음과 같은 코드 조각을 가지고 있습니다. (나는 의미론적인 행동을 reuse parsed variable with boost karma에 기반을 두었습니다).부스트 업 그레 이드 : transform_attribute에 대한이 암시 적 호출은 어떻게 작동합니까? (또는하지 않습니까?)
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <vector>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/sequence.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_bind.hpp>
#include <boost/spirit/include/support_attributes.hpp>
#include <boost/spirit/include/support_adapt_adt_attributes.hpp>
using namespace boost::spirit;
struct DataElement
{
DataElement(const std::string& s) : str_(s) {}
const std::string& str() const { return str_; }
std::string& str() { return str_; }
std::string str_;
};
using Data = std::vector<std::shared_ptr<const DataElement>>;
namespace boost {
namespace spirit {
namespace traits {
template<>
struct transform_attribute<std::shared_ptr<const DataElement> const, const DataElement&, karma::domain>
{
using type = const DataElement&;
static type pre(const std::shared_ptr<const DataElement>& val) { return *val; }
};
}
}
}
BOOST_FUSION_ADAPT_ADT(
DataElement,
(std::string&, const std::string&, obj.str(), obj.str())
);
template<typename Iterator>
struct TheGrammar: public karma::grammar<Iterator, Data()>
{
TheGrammar(): karma::grammar<Iterator, Data()>(start)
{
start %= -(elt % karma::eol);
elt %=
karma::lit("'some prefix'")
<< karma::string [karma::_1 = boost::phoenix::at_c<0>(karma::_val)]
<< karma::lit("'some infix 1'")
<< karma::string [karma::_1 = boost::phoenix::at_c<0>(karma::_val)]
<< karma::lit("'some infix 2'")
<< karma::string [karma::_1 = boost::phoenix::at_c<0>(karma::_val)]
<< karma::lit("'some suffix'")
;
}
karma::rule<Iterator, Data()> start;
karma::rule<Iterator, const DataElement&()> elt;
};
int main(void)
{
Data vec = {
std::make_shared<DataElement>("one"),
std::make_shared<DataElement>("two"),
std::make_shared<DataElement>("three"),
std::make_shared<DataElement>("four"),
std::make_shared<DataElement>("five"),
std::make_shared<DataElement>("six"),
std::make_shared<DataElement>("seven"),
std::make_shared<DataElement>("eight"),
};
using iterator_type = std::ostream_iterator<char>;
iterator_type out(std::cout);
TheGrammar<iterator_type> grammar;
return karma::generate(out, grammar, vec);
}
나는 몇 가지 이해하고 싶습니다
- 왜 난 아무데도
karma::attr_cast
를 사용할 필요가 없습니다를? 내start
규칙은std::shared_ptr
의 벡터이고elt
규칙은 실제 개체 const 참조에서 작동합니다. 나는 원래attr_cast
을 시도했지만 아무데도 가지 않았고, 일종의 노력으로이 버전을 시험해 보았습니다 ... - 사용자 정의
transform_attribute
을 모두 주석으로 처리하면 왜 여전히 컴파일됩니까? 일부 기본값std::shared_ptr<T>
->T&
transform_attribute가 제공됩니까? 많이 찾지는 못했지만 어쩌면 정확한 장소를 찾고 있지 않은 것일까 요? - 위에서 설명한 것처럼 내 사용자 정의
transform_attribute
을 주석 처리하면 코드가 컴파일되지만 런타임에 분명히 메모리가 손상 될 수 있습니다.karma::string
은 쓰레기를 생성합니다. 어떤면에서, 나는 카르마에게 내shared_ptr
에서 물건을 얻는 방법을 알지 못하기 때문에 우스운 일이 일어나야 만한다는 것을 이해할 수 있습니다. 실제 오류/버그를 컴파일하고 있습니까?
시간과 도움을 많이 주셔서 감사합니다.
재 ADT 적응하지 않습니다. 수동으로 attr_cast를 시도하면 (적어도 Spirit의 Qi 부분에서는) 존재하는 흥미로운 버그가 발생할 수 있습니다. attr_cast 내부의 파서 서브 표현식 주위에'qi :: copy()'또는'boost :: proto :: deep_copy()'를 추가하려고 할 수 있습니다. – sehe
FWIW 여기서'attr_cast'와 관련된 버그를 발견했습니다 : http : // /stackoverflow.com/questions/19707254/syntax-tree-empty-nodes-issue-with-spirit-qi-minic-example/19715064#comment31448465_19715064 – sehe