daha fazla ruh madness - çözümleyici-tip (kurallar vs int_parser<>) ve meta-programlama teknikleri
Soru alt kalın, sorun da sonuna doğru damıtma kod parçası tarafından özetlenmiştir.
Tek bir bileşen Lakos olarak yazın sistemimi (tür sistemi string türünden gelen ve yok) birleştirmeye çalışıyorum. boost::array
, boost::variant
, ve bunu başarmak için boost::mpl
, kullanıyorum. Benim tipte bir değişken ile birleştirilmiş için ayrıştırıcı ve jeneratör kurallar olmasını istiyorum. tanımlanmamış bir türü, (aşağıya bakınız) int4 türü ve int8 bir tipi var. Varyant variant<undefined, int4,int8>
olarak okur.
int4 özellikleri:
struct rbl_int4_parser_rule_definition
{
typedef boost::spirit::qi::rule<std::string::iterator, rbl_int4()> rule_type;
boost::spirit::qi::int_parser<rbl_int4> parser_int32_t;
rule_type rule;
rbl_int4_parser_rule_definition()
{
rule.name("rbl int4 rule");
rule = parser_int32_t;
}
};
template<>
struct rbl_type_parser_rule<rbl_int4>
{
typedef rbl_int4_parser_rule_definition string_parser;
};
varyant yukarıda tanımsız olarak başlar, ve sonra ben kuralları başlatılamadı. Yaşadığım bir sorun, neden 50 sayfa hataları, ve sonunda başardı izlemek aşağı, Değişken kullanır operator=
sırasında atama ve boost::spirit::qi::int_parser<>
olamaz atanmış bir operatör=).
Kontrast için, tanımsız tipim ile bir sorunum yok:
struct rbl_undefined_parser_rule_definition
{
typedef boost::spirit::qi::rule<std::string::iterator, void()> rule_type;
rule_type rule;
rbl_undefined_parser_rule_definition()
{
rule.name("undefined parse rule");
rule = boost::spirit::qi::eps;
}
};
template<>
struct rbl_type_parser_rule<rbl_undefined>
{
typedef rbl_undefined_parser_rule_definition string_parser;
};
Sorunun damıtma:
#include <string>
#include <boost/spirit/include/qi.hpp>
#include <boost/variant.hpp>
#include <boost/cstdint.hpp>
typedef boost::spirit::qi::rule<std::string::iterator,void()> r1;
typedef boost::spirit::qi::rule<std::string::iterator,int()> r2;
typedef boost::variant<r1,r2> v;
int main()
{
/*
problematic
boost::spirit::qi::int_parser<int32_t> t2;
boost::spirit::qi::int_parser<int32_t> t1;
t1 = t2;
*/
//unproblematic
r1 r1_;
r2 r2_;
r1_ = r2_;
v v_;
// THIS is what I need to do.
v_ = r2();
}
Beton ayrıştırıcıları ve kuralları arasında anlamsal bir boşluk var. Beynim pramatism düşünmek için gitmiyorum, şu anda sigara içiyorBenim sorum, bu sorunu nasıl çözerim ?Üç yaklaşım sorunu çözmek için düşünebilirim.
bir:Statik işlev üyeleri:
struct rbl_int4_parser_rule_definition
{
typedef boost::spirit::qi::rule<std::string::iterator, rbl_int4()> rule_type;
//boost::spirit::qi::int_parser<rbl_int4> parser_int32_t;
rule_type rule;
rbl_int4_parser_rule_definition()
{
static boost::spirit::qi::int_parser<rbl_int4> parser_int32_t;
rule.name("rbl int4 rule");
rule = parser_int32_t;
}
};
Yaklaşım sanırım bir kod parçacığı güvenli engeller ? ?
iki:İntegral çözümleyici bir shared_ptr sarılır. Yazarak sistemi için TMP ile rahatsız ediyorum iki nedeni vardır: bileşenler 1 etkinliği, 2 merkezileştirmek ilgilidir. işaretçi kullanarak ilk nedeni yendi.
üç:operatör= yok-op olarak tanımlanır. varyant lhs
varsayılan atama önce inşa edilmiş olduğunu garanti eder.
Düzenleme: En mantıklısı (operatör= no-op) yapar 3 seçenek düşünüyorum. Kural konteyner oluşturulduktan sonra değişmez, sadece mahsup tür kuralı sürekli zorlamak için atıyorum.
CEVAP
Soruyu tam ölçüde, bu yüzden emin değilim, ama burada bir kaç ipucu
Hattı
// THIS is what I need to do.
derler bana uyar (sorun çözüldü mü? ile yorumladı Aslında bir çözümleyici, bir kural değil atama demek olduğunu tahmin ediyorum?)Fonksiyon-yerel
static
başlatma, son standart (C 11) parçacığı güvenli olarak tanımlandı. Derleyici C 0 X desteği parçacığı kontrol edin. (Eğer başlatıcı atar, deyim yeniden başlatmayı deneyecek başlatma, arada bir pas.kurallar
alias()
http://boost-spirit.com/home/articles/doc-addendum/faq/#aliases açıklandığı gibi
Mantıklı bir kopya zorunda aslında değer-kopya proto ifadesi olmadan kurallar oluşturabilirsiniz SSS dediği gibi, bu temelde tembel bağlayıcı izin vermek için
Nabialek Trick tam da ihtiyacınız olan şey olabilir, temelde tembel sonraki ayrıştırma için bir ayrıştırıcı seçer
one = id; two = id >> ',' >> id; keyword.add ("one", &one) ("two", &two) ; start = *(keyword[_a = _1] >> lazy(*_a));
Sizin kapsamda,
keyword
tanımlanmış olarak görüyorumqi::symbols<char, qi::rule<Iterator>*> keyword;
semantik eylemleri öznitelikleri ile bütün işi. Alternatif olarak,
qi::symbols<char, qi::rule<Iterator, std::variant<std::string,int>() >*> keyword;
Aynı tür altında kuralları önceki satırda, temelde gösterildiği gibi () getirin
Bu kafam karıştı kısım: tip sistem birleştirmek istediğini söylüyorsun. Strongtyped ayrıştırıcıları (farklı öznitelik imza) ihtiyaç olmayabilir.
typedef boost::variant<std::string,int> unified_type; typedef qi::rule<std::string::iterator, unified_type() > unified_rule; unified_rule rstring = (qi::char_ - '.'); unified_rule rint = qi::int_; unified_rule combine = rstring | rint;
Nasıl MySQL SIRALAMA türü sütun için d...
Neden bu dize uzunluğu daha fazla kara...
Neden't "sağ" daha fazl...
Neredeyse sıralanmış bir dizi (k) elem...
Doğrulama, bir veya daha fazla varlıkl...