Was sind eure lieblings boost funktionen?



  • Bei mir auch thread, spirit, lexical_cast und bind. Und wenn ich's brauche noch filesystem und shared_ptr.



  • shared_ptr und bind. Beide extrem nützlich und dennoch vergleichsweise leichtgewichtig.

    Außerdem mag ich noch Boost.Python. Und Spirit ist zwar irgendwo eine feine Sache, aber teilweise auch schon ziemlich krank...



  • hehe, richtig: filesystem hab ich ganz vergessen - das Zeugs ist mit meinen Programmen bereits so verwachsen das ich gar nicht mehr daran denke von wo es eigentlich kommt 😃

    dooooomi schrieb:

    Und Spirit ist zwar irgendwo eine feine Sache, aber teilweise auch schon ziemlich krank...

    spirit ist für Einsteiger ziemlich unangenehm, aber ich finde nur schon die Art wie man seine Ziele damit erreichen kann wesentlich eleganter als z.B. regular expressions 😋


  • Administrator

    boosOR schrieb:

    spirit ist für Einsteiger ziemlich unangenehm, aber ich finde nur schon die Art wie man seine Ziele damit erreichen kann wesentlich eleganter als z.B. regular expressions 😋

    Naja, Xpressive gefallen mir irgendwie besser als Spirit. Obwohl ich allerdings zugeben muss, dass ich bisher glaub ich noch nie mit der neuen Spirit Version gearbeitet habe. Aber Spirit ist irgendwie klobig zu verwenden. Grammatiken zu definieren, arten in absolut unleserlichen Code aus und das gefällt mir gar nicht an Spirit.

    Grüssli



  • turboboost schrieb:

    Was sind eure lieblings boost funktionen und was verwendet ihr am häufigsten?

    Im wesentlichen das, was es auch in den nächsten Standard schafft, oder bereits im TR1 enthalten ist: bind, function, shared_ptr, scoped_ptr



  • Dravere schrieb:

    Aber Spirit ist irgendwie klobig zu verwenden. Grammatiken zu definieren, arten in absolut unleserlichen Code aus und das gefällt mir gar nicht an Spirit.

    Ich finde Spirit einfach nur genial, hier mal ein Beispiel:

    #include <iostream>
    #include <string>
    #include <boost/spirit.hpp>
    
    int main()
    {
    	const char* line = "GET /path/to/file/index.html HTTP/1.0";
    	std::string http_verb, http_path, http_version;
    
    	using namespace boost::spirit;
    	// Hilfsregeln:
    	rule<> verb    = strlit<>("GET") | strlit<>("POST");
    	rule<> path    = *( alnum_p | '/' | '-' | '.' );
    	rule<> version = strlit<>("HTTP/1.0") | strlit<>("HTTP/1.1");
    
    	// Volle Regel:
    	rule<> r       = verb [assign_a(http_verb)] >> +space_p >> path [assign_a(http_path)] >> +space_p >> version [assign_a(http_version)];
    
    	// Parsen:
    	if ( parse<>( line, r, space_p ).full )
    	{
    		std::cout << "Verb: '" << http_verb << "'" << std::endl;
    		std::cout << "Path: '" << http_path << "'" << std::endl;
    		std::cout << "Version: '" << http_version << "'" << std::endl;
    	}
    }
    

  • Administrator

    verb [assign_a(http_verb)] >> +space_p >> path [assign_a(http_path)] >> +space_p >> version [assign_a(http_version)];
    Ja, genau diese wunderschönen Zeilen! Und das ist noch eine einfache Grammatik, mach das mal mit komplexen Grammatiken. Entweder brauchst du 10 Bildschirme nebeneinander oder 2-3 untereinander.

    Und wenn du dann noch dynamische Grammatiken brauchst, das wird sowas von komplex und lang. Das sieht einfach nur noch hässlich aus. Zudem definiert man mit der Zeit duzende und noch mehr an rule Variablen und packt damit ganze Klassen voll. Und wenn man dann noch subrule verwendet oder grammatic ... da wird es einem einfach nur schlecht!

    Grüssli



  • Dravere schrieb:

    verb [assign_a(http_verb)] >> +space_p >> path [assign_a(http_path)] >> +space_p >> version [assign_a(http_version)];
    Ja, genau diese wunderschönen Zeilen! Und das ist noch eine einfache Grammatik, mach das mal mit komplexen Grammatiken. Entweder brauchst du 10 Bildschirme nebeneinander oder 2-3 untereinander.

    Und wenn du dann noch dynamische Grammatiken brauchst, das wird sowas von komplex und lang. Das sieht einfach nur noch hässlich aus. Zudem definiert man mit der Zeit duzende und noch mehr an rule Variablen und packt damit ganze Klassen voll. Und wenn man dann noch subrule verwendet oder grammatic ... da wird es einem einfach nur schlecht!

    Grüssli

    Mag sein, jedoch hat man wenigstens ein einheitliches System wie die Probleme zu lösen sind. Schreib erst mal von Hand so einen Parser und dann schauen wird nochmals was schlussendlich komplexer aussieht^^ spirit gehört einfach zu den wirklich grossen Geschützen und bringt deshalb gezwungenermassen eine gewisse Komplexität mit sich 😉



  • Dravere schrieb:

    Ja, genau diese wunderschönen Zeilen! Und das ist noch eine einfache Grammatik, mach das mal mit komplexen Grammatiken.

    Dann sag doch mal, was du unter einer komplexen Grammatik verstehst. Der Spirit-Code um C++-Quelltext zu parsen ist jedenfalls noch recht übersichtlich.

    PS: Und wie sieht das Gleiche in XPression aus?



  • Badestrand schrieb:

    Ich finde Spirit einfach nur genial, hier mal ein Beispiel:

    Ist das Spirit2? Ich kriege deinen Code bei mir jedenfalls nicht kompiliert. Welche Boost-Version brauche ich dafür?



  • dooooomi schrieb:

    Badestrand schrieb:

    Ich finde Spirit einfach nur genial, hier mal ein Beispiel:

    Ist das Spirit2? Ich kriege deinen Code bei mir jedenfalls nicht kompiliert. Welche Boost-Version brauche ich dafür?

    Müsste Spirit eins sein, bei mir kompiliert's mit boost 1.35. Welche Fehler kommen denn?



  • Badestrand schrieb:

    Müsste Spirit eins sein, bei mir kompiliert's mit boost 1.35. Welche Fehler kommen denn?

    Das hier sagt der gcc 4.1.2 dazu (mit boost 1.34.1):

    /usr/include/boost/spirit/core/non_terminal/impl/rule.ipp: In member function ‘typename boost::spirit::parser_result<DerivedT, ScannerT>::type boost::spirit::impl::rule_base<DerivedT, EmbedT, T0, T1, T2>::parse_main(const ScannerT&) const [with ScannerT = boost::spirit::scanner<const char*, boost::spirit::scanner_policies<boost::spirit::skipper_iteration_policy<boost::spirit::iteration_policy>, boost::spirit::match_policy, boost::spirit::action_policy> >, DerivedT = boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>, EmbedT = const boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>&, T0 = boost::spirit::nil_t, T1 = boost::spirit::nil_t, T2 = boost::spirit::nil_t]’:
    /usr/include/boost/spirit/core/non_terminal/impl/rule.ipp:171:   instantiated from ‘typename boost::spirit::parser_result<DerivedT, ScannerT>::type boost::spirit::impl::rule_base<DerivedT, EmbedT, T0, T1, T2>::parse(const ScannerT&) const [with ScannerT = boost::spirit::scanner<const char*, boost::spirit::scanner_policies<boost::spirit::skipper_iteration_policy<boost::spirit::iteration_policy>, boost::spirit::match_policy, boost::spirit::action_policy> >, DerivedT = boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>, EmbedT = const boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>&, T0 = boost::spirit::nil_t, T1 = boost::spirit::nil_t, T2 = boost::spirit::nil_t]’
    /usr/include/boost/spirit/core/scanner/impl/skipper.ipp:131:   instantiated from ‘static boost::spirit::parse_info<IteratorT> boost::spirit::impl::phrase_parser<boost::spirit::space_parser>::parse(const IteratorT&, const IteratorT&, const ParserT&, const boost::spirit::space_parser&) [with IteratorT = const char*, ParserT = boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>]’
    /usr/include/boost/spirit/core/scanner/impl/skipper.ipp:153:   instantiated from ‘boost::spirit::parse_info<IteratorT> boost::spirit::parse(const IteratorT&, const IteratorT&, const boost::spirit::parser<DerivedT>&, const boost::spirit::parser<SkipT>&) [with IteratorT = const char*, ParserT = boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>, SkipT = boost::spirit::space_parser]’
    /usr/include/boost/spirit/core/scanner/impl/skipper.ipp:171:   instantiated from ‘boost::spirit::parse_info<const CharT*> boost::spirit::parse(const CharT*, const boost::spirit::parser<DerivedT>&, const boost::spirit::parser<SkipT>&) [with CharT = char, ParserT = boost::spirit::rule<boost::spirit::nil_t, boost::spirit::nil_t, boost::spirit::nil_t>, SkipT = boost::spirit::space_parser]’
    foo.cc:20:   instantiated from here
    /usr/include/boost/spirit/core/non_terminal/impl/rule.ipp:189: error: no matching function for call to ‘boost::spirit::impl::abstract_parser<boost::spirit::scanner<const char*, boost::spirit::scanner_policies<boost::spirit::iteration_policy, boost::spirit::match_policy, boost::spirit::action_policy> >, boost::spirit::nil_t>::do_parse_virtual(const boost::spirit::scanner<const char*, boost::spirit::scanner_policies<boost::spirit::skipper_iteration_policy<boost::spirit::iteration_policy>, boost::spirit::match_policy, boost::spirit::action_policy> >&)’
    /usr/include/boost/spirit/core/non_terminal/impl/rule.ipp:213: note: candidates are: typename boost::spirit::match_result<ScannerT, AttrT>::type boost::spirit::impl::abstract_parser<ScannerT, AttrT>::do_parse_virtual(const ScannerT&) const [with ScannerT = boost::spirit::scanner<const char*, boost::spirit::scanner_policies<boost::spirit::iteration_policy, boost::spirit::match_policy, boost::spirit::action_policy> >, AttrT = boost::spirit::nil_t]
    


  • Hm, tut mir Leid, da kann ich dir leider auch nicht weiterhelfen 😞


  • Administrator

    Badestrand schrieb:

    Dann sag doch mal, was du unter einer komplexen Grammatik verstehst. Der Spirit-Code um C++-Quelltext zu parsen ist jedenfalls noch recht übersichtlich.

    Zum Beispiel ein XML-Parser. Wenn meiner auch nicht ganz zu 100% Standardkonform ist, aber so gut wie möglich. Kommt an den TinyXML Parser ran.

    Ich wollte meinen Parser durch einen Boost.Spirit Parser ersetzen, ca. nach einem Drittel habe ich es abgebrochen. Habe lieber 10-15 private Funktionen, welche den Parser implementieren. Das andere sah einfach nur hässlich aus.

    Badestrand schrieb:

    PS: Und wie sieht das Gleiche in XPression aus?

    Gerade für sowas ist Xpressive extrem geeignet. Das würde wohl irgendwie so aussehen:

    #include <boost/xpressive/xpressive.hpp>
    
    #include <string>
    #include <iostream>
    
    int main()
    {
      std::string line = "GET /path/to/file/index.html HTTP/1.0";
    
      using namespace boost::xpressive;
    
      sregex verb = as_xpr("GET") | "POST";
      sregex path = *(alnum | '/' | '-' | '.');
      sregex version = as_xpr("HTTP/1.0") | "HTTP/1.1";
    
      sregex r = (s1 = verb) >> +space >>
                 (s2 = path) >> +space >>
                 (s3 = version);
    
      // Das oben finde ich schön strukturiert, so s1,s2,s3 übereinander.
      // Aus fairness aber auch noch iner einer Zeile, wo es immer noch deutlich kürzer ist.
    
      /*
      sregex r = (s1 = verb) >> +space >> (s2 = path) >> +space >> (s3 = version);
      */
    
      smatch what;
    
      if(regex_match(line, what, r))
      {
        std::cout << what[1] << std::endl;
        std::cout << what[2] << std::endl;
        std::cout << what[3] << std::endl;
      }
      else
      { std::cout << "Match failed!" << std::endl; }
    
      return 0;
    }
    

    Man beachte, wie man die Werte wunderbar herausfiltern kann. Keine mühsamen Funktoren an die Grammatik binden. Sicher ist das einer der grossen Stärken von Spirit, aber auf der anderen Seite gerade etwas, was die Übersichtlichkeit extrem verschlechtert.

    Anstatt einer Grammatik, welche man extrem schlecht mit Funktoren oder irgendetwas dynamisches verbinden kann, lieber viele verschiedene statische Xpressiv Ausdrücke aufgeteilt auf verschiedene Funktionen. Vor allem ist die dynamik dann viel einfacher, da man die Grammatik während der Laufzeit mit normalen C++ Mitteln verändern kann. Und dabei meine ich nicht nur if, while, for usw. sondern man kann auch Regex Ausdrücke mit den statischen mischen.

    Mag sein, dass Spirit dafür etwas schneller ist, aber ich habe lieber einen etwas langsameren Code, dafür eine Übersicht.

    Grüssli



  • Cool, sieht ja von der Syntax recht ähnlich aus. Die Sache mit (s1=rule) statt (rule[assign_a(var)] sieht auch schöner aus, obwohl es sich nicht viel nimmt.
    Da die Tokens erst hinterher herausgefiltert werden (what[x]), funktioniert das denn noch halbwegs komfortablel bei einer Liste, z.B. wenn unbestimmt viele Pfade (in dem HTTP-Beispiel) möglich sind, oder auch *int_val >> *float_val ?
    Wie dem auch sei, ich werd's mir mal näher angucken, sieht vielversprechend aus 🙂



  • Ich nutze vor allem die Tools, die einem das normale C++-Programmiererleben leichter machen und weniger die Speziallibraries: boost::noncopyable, boost/cstdint.hpp, boost::tuple, shared_ptr/scoped_ptr, STATIC_ASSERT, type_traits, mpl etc.

    Badestrand schrieb:

    Dravere schrieb:

    Ja, genau diese wunderschönen Zeilen! Und das ist noch eine einfache Grammatik, mach das mal mit komplexen Grammatiken.

    Dann sag doch mal, was du unter einer komplexen Grammatik verstehst. Der Spirit-Code um C++-Quelltext zu parsen ist jedenfalls noch recht übersichtlich.

    PS: Und wie sieht das Gleiche in XPression aus?

    Es gibt einen Spirit-Code um C++-Quelltext zu parsen? Link bitte!





  • Phoemuex schrieb:

    http://spirit.sourceforge.net/repository/grammars/show_contents.php

    EDIT: Ist aber nicht wirklich toll...

    Den finde ich sogar noch vergleichsweise hübsch, aber viel mehr als Schlüsselwörter erkennen und sowas macht der ja auch nicht.

    Ansonsten gibt es noch Boost.Wave (C/C++-Präprozessor) und Hannibal. Und da ist's dann auf einmal schon nicht mehr ganz so schön...



  • rüdiger schrieb:

    Es gibt einen Spirit-Code um C++-Quelltext zu parsen? Link bitte!

    Den Link hab ich nicht mehr, hatte ich irgendwo bei Google.de/CodeSearch gefunden. Ich schau mal, ob ich ihn auf die Schnelle noch mal finde.

    edit: Finde ihn grad nicht mehr 😕



  • Hat hier irgendwer nen Vorschlag, wo ich mich am besten (bevorzugt im Internet und erstma ohne Buch) in solche generellen Pars-Grammatik-Ideen einlesen kann? Im Moment versteh ich nur Bahnhof, wenn ich die Spirit-Docu anschaue.


Anmelden zum Antworten