2013-07-24 34 views
11

Ich habe versucht, einige der Boost-Fusion-Sachen zu verwenden, um eine reguläre c-Struktur in Datei zu schreiben. Eine XML-Datei scheint eine gute Möglichkeit zu sein, die Daten zu erfassen und sie mit anderen Werkzeugen kompatibel zu machen oder von Hand editierbar zu machen. Es scheint, als hätte ich es fast, aber etwas Grundlegendes scheint zu fehlen. Ich benutze etwas, das dem auf der boost :: fusion-Schnellstartseite ziemlich ähnlich ist: http://www.boost.org/doc/libs/1_54_0/libs/fusion/doc/html/fusion/quick_start.html. Als Randnotiz habe ich mich hier und in Boosts Dokumentation gründlich umgeschaut, aber niemand scheint auf den Feldnamen zuzugreifen.Zugriff auf Boost-Fusion-Map-Feldname

struct print_xml 
{ 
    template <typename T> 
    void operator()(T const& x) const 
    { 
     std::cout 
      << '<' << x.first << '>' 
      << x 
      << "</" << x.first << '>' 
      ; 
    } 
}; 

Ich möchte es wie folgt verwenden:

BOOST_FUSION_ADAPT_STRUCT(
    myStructType, 
    (double, val1) 
    (double, val2) 
    (char, letter) 
    (int, number) 
    )  
myStructType saveMe = { 3.4, 5.6, 'g', 9}; 
for_each(saveMe, print_xml()); 

Andere Male habe ich die Struktur wie folgt definiert, aber noch kein Glück:

namespace fields{ 
    struct val1; 
    struct val2; 
    struct letter; 
    struct number; 
} 

typedef fusion::map< 
    fusion::pair<fields::val1, double>, 
    fusion::pair<fields::val2, double>, 
    fusion::pair<fields::letter, char>, 
    fusion::pair<fields::number, int> > myStructType; 

Ich weiß, es ist kein Mitglied zuerst , aber es scheint wirklich so zu sein, um auf den Feldnamen zugreifen zu können! Der Code, den ich habe, funktioniert gut mit x.second aber erreicht dann nicht, was ich brauche, um den Feldnamen zu bekommen. Wie sonst könnte ich das erreichen? Danke!

Antwort

14
#include <iostream> 
#include <string> 

#include <boost/mpl/range_c.hpp> 
#include <boost/fusion/include/for_each.hpp> 
#include <boost/fusion/include/zip.hpp> 
#include <boost/fusion/include/at_c.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 
#include <boost/fusion/include/mpl.hpp> 

namespace fusion=boost::fusion; 
namespace mpl=boost::mpl; 

struct myStructType 
{ 
    double val1; 
    double val2; 
    char letter; 
    int number; 
}; 

BOOST_FUSION_ADAPT_STRUCT(
    myStructType, 
    (double, val1) 
    (double, val2) 
    (char, letter) 
    (int, number) 
) 



template <typename Sequence> 
struct XmlFieldNamePrinter 
{ 
    XmlFieldNamePrinter(const Sequence& seq):seq_(seq){} 
    const Sequence& seq_; 
    template <typename Index> 
    void operator() (Index idx) const 
    { 
     //use `Index::value` instead of `idx` if your compiler fails with it 
     std::string field_name = fusion::extension::struct_member_name<Sequence,idx>::call(); 

     std::cout 
      << '<' << field_name << '>' 
      << fusion::at<Index>(seq_) 
      << "</" << field_name << '>' 
      ; 
    } 
}; 
template<typename Sequence> 
void printXml(Sequence const& v) 
{ 
    typedef mpl::range_c<unsigned, 0, fusion::result_of::size<Sequence>::value > Indices; 
    fusion::for_each(Indices(), XmlFieldNamePrinter<Sequence>(v)); 
} 

int main() 
{ 
    myStructType saveMe = { 3.4, 5.6, 'g', 9}; 
    printXml(saveMe); 
} 
+1

Erstaunliches Stück:/Ich hatte keine Ahnung, dass das existierte – sehe