Arka plan soru: boost.proto + detect invalid terminal before building the expression tree.boost.proto + İfade ağacını yerinde değiştir
Merhaba, ne ben başarmak için çalışıyorum
- tüm vektörler onların başlamak yineleyiciler ile ikame edilir bir ifade ağacının, bir kopyasını oluşturmak (benim durumumda bir ham işaretçi edilir)
- olduğunu Yineleyicileri yinelemek için
- ağaçtaki dereference yineleyicileri, ancak bu bölüm nispeten kolay olmalıdır.
Yani, 1 için bu kod yukarıdaki tüm vektörler işaretçiler yerini bir ağacı oluşturmak için başarılı
///////////////////////////////////////////////////////////////////////////////
// A transform that converts all vectors nodes in a tree to iterator nodes
struct vector_begin : proto::transform <vector_begin>
{
template<typename Expr, typename Unused1, typename Unused2>
struct impl : boost::proto::transform_impl<Expr, Unused1, Unused2>
{
// must strip away the reference qualifier (&)
typedef typename proto::result_of::value<
typename boost::remove_reference<Expr>::type
>::type vector_type;
typedef typename proto::result_of::as_expr
<typename vector_type::const_iterator>::type result_type;
result_type operator()(
typename impl::expr_param var
, typename impl::state_param
, typename impl::data_param) const
{
typename vector_type::const_iterator iter(proto::value(var).begin());
return proto::as_expr(iter); // store iterator by value
}
};
};
struct vector_grammar_begin
: proto::or_ <
proto::when <vector_terminal, vector_begin>
// scalars want to be stored by value (proto stores them by const &), if not the code does not compile...
, proto::when <scalar_terminal, boost::proto::_make_terminal(boost::proto::_byval(boost::proto::_value))>
// descend the tree converting vectors to begin() iterators
, proto::when <proto::nary_expr<_, proto::vararg<vector_grammar_begin> > >
>
{};
ile sona erdi. Çok uzak çok iyi. Şimdi yineleyicileri artırmaya çalışın. Yineleyicileri ilerletmenin daha iyi olacağını fark ettim, bu yüzden sadece bir dönüşümle, rastgele bir erişim yineleyicisinin davranışının çoğunu elde edebilirim (dereference diğer eksik parçadır). 2. için, ana işlevi, Şimdi
///////////////////////////////////////////////////////////////////////////////
// A transform that advances all iterators in a tree
struct iter_advance : proto::transform <iter_advance>
{
template<typename Expr, typename Index, typename Dummy>
struct impl : boost::proto::transform_impl<Expr, Index, Dummy>
{
typedef void result_type;
result_type operator()(
typename impl::expr_param var
, typename impl::state_param index // i'm using state to pass a data :(
, typename impl::data_param) const
{
proto::value(var)+=index; // No good... compile error here :(
}
};
};
// Ok, this is brittle, what if I decide the change vector<D,T>'s iterator type ?
struct iter_terminal
: proto::and_<
proto::terminal<_>
, proto::if_<boost::is_pointer<proto::_value>()>
>
{};
struct vector_grammar_advance
: proto::or_ <
proto::when <iter_terminal, iter_advance>
, proto::terminal<_>
, proto::when <proto::nary_expr<_, proto::vararg<vector_grammar_advance> > >
>
{};
olmalıdır dönüşümü gerekli
template <class Expr>
void check_advance (Expr const &e)
{
proto::display_expr (e);
typedef typename boost::result_of<vector_grammar_begin(Expr)>::type iterator_type;
iterator_type iter = vector_grammar_begin()(e);
proto::display_expr (iter);
vector_grammar_advance()(iter,1);
proto::display_expr (iter);
}
int main (int, char**)
{
vec<3, double> a(1), b(2), c(3);
check_advance(2*a+b/c);
return 0;
}
alıyorum (önemsiz filtrelenen) aşağıdaki hata iletisi:
array.cpp: 361: 13: hata: salt okunur yerin tahsisi
'boost::proto::value<boost::proto::exprns_::expr<boost::proto::tagns_::tag::terminal,
boost::proto::argsns_::term<const double*>, 0l> >((* & var))'
beni asıl rahatsız olduğu '((* & var)) 'kısım ... bunu düzeltmek için ne yapacağımı anlayamıyorum. peşin sayesinde, saygılarımla
PS İlgisiz şey: dönüşümler biraz oynadıktan sonra, ben kullanıyorum genel kalıptır:
- ağaca neler yapacağınıza karar verin
- İşlemi gerçekleştiren bir ilkel dönüşüm yazın
- Dönüştürmenin uygulanacağı yeri tanımlayan bir dilbilgisi yazın.
Bunun makul olduğunu düşünüyor musunuz? Yani, tek bir tür düğümüne sadece bir temel işlem gerçekleştirmek için çok fazla kod var. Bağlamlarda, düğüm tipinde ayrım yaparak, bir kerede birden fazla ops tanımlamak mümkündür. Bunu da dönüşümlerle yapmak mümkün mü? Kullanılacak genel model nedir?
Hata iletisi, 'var' (indeksle arttırma girişiminde bulunduğunuz yer) immutable olduğu anlamına gelir. Dönüşümün bir sonraki yineleyiciyi döndürdüğü daha işlevsel bir stili kullanmayı denediniz mi? –
@LucDanton İter_advance içinde dönüş türünü değiştirirseniz ve değiştirilmiş bir işaretçi döndürdüm (dönüştürmede işaretçinin artırıldığını doğruladım), ağaç değiştirilmez. Ben proto-manaual üzerinde 'increment_ints' takip ediyordum, ama şimdi fark ettim ki, bu durumda, ağaç int vars'a referanslar saklıyordu, simdi ptr'lerin ağaçtaki değere göre depolandım. Alternatifler: 1. Arttırdığım her seferinde bütün ağacın yeni bir kopyasını hazırlayın (tamamen işlevsel yaklaşım?) B) imleci, kılavuzun 'karışık' örneğinde olduğu gibi bir iterator_wrapper içinde saklayın. – Giuliano