У меня есть следующий фрагмент кода, который, кажется, работает нормально (я основывал семантические действия на reuse parsed variable with boost karma).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
к объектам. Является ли тот факт, что он компилирует фактическую ошибку/ошибку?
Большое спасибо за ваше время и помощь!
повторно. Вручая попытку attr_cast, вы, возможно, столкнулись с интересной ошибкой, которая существовала (по крайней мере, в части Qi Spirit). Вы можете попытаться добавить 'qi :: copy()' или 'boost :: proto :: deep_copy()' вокруг подвыражения парсера внутри attr_cast – sehe
FWIW Вот где я нашел эту ошибку с 'attr_cast': http://stackoverflow.com/questions/19707254/syntax-tree-empty-nodes-issue-with-spirit-qi-minic-example/19715064#comment31448465_19715064 – sehe