2009-06-05 15 views
10

सी ++ बनाने की मेरी महाकाव्य खोज में चीजें नहीं करना चाहिए, मैं एक संकलित समय उत्पन्न कक्षा को एक साथ रखने की कोशिश कर रहा हूं।सी ++ कोड जनरेशन

एक पूर्वप्रक्रमक परिभाषा के आधार पर, इस तरह के रूप (किसी न किसी अवधारणा)

CLASS_BEGIN(Name) 
    RECORD(xyz) 
    RECORD(abc) 

    RECORD_GROUP(GroupName) 
     RECORD_GROUP_RECORD(foo) 
     RECORD_GROUP_RECORD(bar) 
    END_RECORDGROUP 
END_CLASS 

जबकि मैं काफी यकीन है कि मैं एक वर्ग है कि (संरचना इस तरह की का उपयोग कर फ़ाइल सिस्टम से डेटा पढ़ता है शायद यह कर उत्पन्न कर रहा हूँ टेम्पलेट मेटाप्रोग्रामिंग का उपयोग करके), मैं नहीं देखता कि डेटा को पढ़ने के लिए डेटा और फ़ंक्शन तक पहुंचने के लिए मैं दोनों कार्यों को कैसे उत्पन्न कर सकता हूं।

मैं इस तरह एक वर्ग कुछ के साथ खत्म करना चाहते हैं

class Name{ 
    public: 
    xyz_type getxyz(); 
    void setxyz(xyz_type v); 

    //etc 

    list<group_type> getGroupName(); 

    //etc 

    void readData(filesystem){ 
     //read xyz 
     //read abc 
     //etc 
    } 
}; 

किसी को भी अगर यह भी संभव है किसी भी विचार है?

--EDIT--

इस लिए करना उपयोग स्पष्ट करने के लिए। मेरे पास एक मानक प्रारूप में फ़ाइलें हैं जिन्हें मैं पढ़ना चाहता हूं। प्रारूप पहले ही परिभाषित किया गया है, इसलिए यह बदलने के लिए खुला नहीं है। प्रत्येक फ़ाइल में कोई भी संख्या रिकॉर्ड हो सकता है, जिनमें से प्रत्येक में कोई भी उप-रिकॉर्ड हो सकता है।

कई रिकॉर्ड प्रकारों में प्रत्येक के उप-रिकॉर्ड का एक अलग सेट होता है, लेकिन उन्हें परिभाषित किया जा सकता है। तो उदाहरण के लिए, ऊंचाईमैप रिकॉर्ड में ऊंचाईमैप होना चाहिए, लेकिन वैकल्पिक में मानक हो सकते हैं।

तो मैं तो जैसे कि के लिए एक रिकार्ड को परिभाषित करना चाहते हैं:

class Heightmap{ 
    public: 
    std::string getHeightmap(){ 
     return mHeightmap->get<std::string>(); 
    } 
    void setHeightmap(std::string v){ 
     mHeight->set<std::string>(v); 
    } 

    bool hasNormal(){ 
     return mNormal != 0; 
    } 
    //getter and setter functions for normals go here 

    private: 
    void read(Record* r){ 
     mHeightmap = r->getFirst(VHDT); 
     mNormal = r->getFirst(VNML); 
    } 


    SubRecord* mHeightmap, mNormal; 
} 

मुद्दा:

CLASS_BEGIN(Heightmap) 
    RECORD(VHDT, Heightmap, std::string) //Subrecord Name, Readable Name, Type 
    RECORD_OPTIONAL(VNML, Normals, std::string) 
END_CLASS 

जो के लिए मैं इस तरह एक वर्ग की कार्यक्षमता के साथ उत्पादन कुछ चाहेगा मुझे लगता है कि मुझे हर प्रीप्रोसेसर परिभाषा की दो बार आवश्यकता है। एक बार कक्षा के भीतर फ़ंक्शन परिभाषा को परिभाषित करने के लिए, और एक बार पढ़ने के फ़ंक्शन को बनाने के लिए। चूंकि प्रीप्रोसेसर पूरी तरह कार्यात्मक है, इसलिए मैं डेटा को कतार में धक्का नहीं दे सकता और कक्षा को END_CLASS मार्को परिभाषा पर उत्पन्न नहीं कर सकता।

मुझे इस मुद्दे के आसपास कोई रास्ता नहीं दिखाई दे रहा है, लेकिन आश्चर्य हुआ कि अगर किसी को सी ++ की अधिक समझ हो।

+0

यह संभव है, मुझे संदेह है। क्या आप दीवार पर टक्कर मार रहे हैं, इस बारे में अधिक सटीक हो सकते हैं? –

+0

यह स्पष्ट नहीं है कि आपको ऐसा करने से क्या फायदे हैं - कृपया समझाएं। –

उत्तर

5

आप tuples को बढ़ावा देने के द्वारा इस समस्या को हल करने में सक्षम हो सकते हैं। इसके परिणामस्वरूप एक ऐसा डिज़ाइन होगा जो आप अब के बारे में सोच रहे हैं, लेकिन यह आपको सामान्य तरीके से समस्या को हल करने की अनुमति दे सकता है।

निम्न उदाहरण "std :: string, bool" फ़ॉर्म का रिकॉर्ड परिभाषित करता है और फिर उस डेटा को स्ट्रीम से पढ़ता है।

#include "boost/tuple/tuple.hpp" 
#include <iostream> 
#include <sstream> 

using namespace ::boost::tuples; 

फ़ंक्शंस का उपयोग एक आईट्रीम से डेटा को पढ़ने के लिए किया जाता है। पहले अधिभार टपल के माध्यम से यात्रा बंद हो जाता है जो हमने पिछले रिकॉर्ड प्रकार तक पहुँचने के बाद:

// 
// This is needed to stop when we have no more fields 
void read_tuple (std::istream & is, boost::tuples::null_type) 
{ 
} 

template <typename TupleType> 
void read_tuple (std::istream & is, TupleType & tuple) 
{ 
    is >> tuple.template get_head(); 
    read_tuple (is, tuple.template get_tail()); 
} 

निम्नलिखित वर्ग हमारे रिकॉर्ड गेटर सदस्य लागू करता है। हमारे कुंजी के रूप में RecordKind इस्तेमाल करते हुए हम विशिष्ट सदस्य है कि हम में रुचि रखते हैं मिलता है।

template <typename TupleType> 
class Record 
{ 
private: 
    TupleType m_tuple; 

public: 
    // 
    // For a given member - get the value 
    template <unsigned int MBR> 
    typename element <MBR, TupleType>::type & getMember() 
    { 
    return m_tuple.template get<MBR>(); 
    } 

    friend std::istream & operator>> (std::istream & is 
            , Record<TupleType> & record) 
    { 
    read_tuple (is, record.m_tuple); 
    } 
}; 

अगले प्रकार हमारे रिकार्ड के लिए मेटा वर्णन है। गणना हमें एक प्रतीकात्मक नाम देती है जिसे हम सदस्यों तक पहुंचने के लिए उपयोग कर सकते हैं, यानी। क्षेत्र के नाम

struct HeightMap 
{ 
    enum RecordKind 
    { 
    VHDT 
    , VNML 
    }; 

    typedef boost::tuple < std::string 
         , bool 
        > TupleType; 
}; 

अंत में, हम एक रिकॉर्ड का निर्माण और एक धारा से कुछ डेटा में पढ़ा:

int main() 
{ 
    Record<HeightMap::TupleType> heightMap; 
    std::istringstream iss ("Hello 1"); 

    iss >> heightMap; 

    std::string s = heightMap.getMember <HeightMap::VHDT>(); 
    std::cout << "Value of s: " << s << std::endl; 


    bool b = heightMap.getMember <HeightMap::VNML>(); 
    std::cout << "Value of b: " << b << std::endl; 
}  

और जैसा कि यह सब टेम्पलेट कोड है, तो आप होना चाहिए टपल तो उन क्षेत्रों के प्रकार को परिभाषित करता है रिकॉर्ड में घोंसला रिकॉर्ड करने में सक्षम है।

8

यदि आप सी ++ कोड जनरेशन के साथ डेटा को क्रमबद्ध/deserialize करने का कोई तरीका ढूंढ रहे हैं, तो मैं Google protobufs (http://code.google.com/p/protobuf/) या फेसबुक के थ्रिफ्ट (http://incubator.apache.org/thrift/) पर देखता हूं।

protobufs के लिए, आप लिखते हैं तो जैसे एक डेटा परिभाषा:

message Person { 
    required string name = 1; 
    required int32 id = 2; 
    optional string email = 3; 

    enum PhoneType { 
    MOBILE = 0; 
    HOME = 1; 
    WORK = 2; 
    } 

    message PhoneNumber { 
    required string number = 1; 
    optional PhoneType type = 2 [default = HOME]; 
    } 

    repeated PhoneNumber phone = 4; 
} 

एक व्यक्ति सी ++ वर्ग तो उत्पन्न होता है कि आप लोड, बचाने के लिए और इस डेटा का उपयोग करने देता है। तुम भी अजगर, जावा, आदि उत्पन्न कर सकते हैं

2

मैं इसी तरह कुछ करने के लिए एक रिकार्ड mixin के साथ चारों ओर निभा सकता है - स्वतः एक वर्ग में कार्यक्षमता जोड़ने के संकलन समय

template<class Base, class XyzRecType> 
    class CRecord : public Base 
    { 
    protected: 
     RecType xyz; 
    public: 
     CRecord() : Base() {} 


     RecType Get() {return xyz;} 

     void Set(const RecType& anXyz) {xyz = anXyz;} 

     void ReadFromStream(std::istream& input) 
     { 
      ... 
     } 

    }; 

    class CMyClass 
    { 
    }; 

    int main() 
    { 
     // now thanks to the magic of inheritance, my class has added methods! 
     CRecord<CMyClass, std::string> myClassWithAStringRecord; 

     myClassWithAStringRecord.Set("Hello"); 

    } 
0

पर मैं बिल्कुल यकीन नहीं है आप कुछ मामलों में क्या खोज रहे हैं।

  • विनिर्देश में foo और bar का क्या होता है?
  • ग्रुपनाम वास्तव में क्या मिलता है? (Foo, बार)? या समूह नाम?

ऐसा लगता है कि आप मनमाने ढंग से लेआउट की डिस्क संरचनाओं को लोड और एक्सेस करने के लिए एक तंत्र बनाने की कोशिश कर रहे हैं। क्या यह सही है? (संपादित करें: बस "सेट" सदस्य फ़ंक्शन पर ध्यान दिया गया है ... इसलिए मुझे लगता है कि आप पूर्ण क्रमबद्धता की तलाश में हैं)

यदि आप * निक्स सिस्टम पर हैं, तो अपने स्वयं के कंपाइलर को .o (संभवतः संकलित करने के लिए निर्दिष्ट करें) मेकफ़ाइल में एक पर्ल/पायथन/क्या है-आप स्क्रिप्ट जो जीसीसी को कॉल के साथ समाप्त होती है) एक मामूली समाधान है। दूसरों को विंडोज़ पर ऐसा करने के तरीकों के बारे में पता हो सकता है।

3

यह एक तकनीक है जिसे मैं सी और सी ++ में बहुत कुछ उपयोग करता हूं, जिसे "सूची मैक्रो" कहा जाता है। मान लें कि आपके पास चर, त्रुटि संदेश, दुभाषिया opcodes, या कुछ भी है जो दोहराव कोड लिखने की जरूरत है की एक सूची है। आपके मामले में यह वर्ग सदस्य चर है।

मान लीजिए कि यह चर है। इस प्रकार की सूची मैक्रो में डाल:

#define MYVARS \ 
DEFVAR(int, a, 6) \ 
DEFVAR(double, b, 37.3) \ 
DEFARR(char, cc, 512) \ 

चर घोषित करने के लिए, ऐसा करते हैं:

#define DEFVAR(typ,nam,inival) typ nam = inival; 
#define DEFARR(typ,nam,len) typ nam[len]; 
    MYVARS 
#undef DEFVAR 
#undef DEFARR 

अब तुम सिर्फ DEFVAR और DEFARR को पुनर्परिभाषित, और instantiating MYVARS द्वारा दोहराए कोड किसी भी प्रकार उत्पन्न कर सकते हैं ।

कुछ लोगों को यह बल्कि झटकेदार लगता है, लेकिन मुझे लगता है कि प्रीप्रोसेसर को कोड जनरेटर के रूप में उपयोग करने और डीआरवाई को पूरा करने का यह एक अच्छा तरीका है। और, सूची मैक्रो स्वयं मिनी-डीएसएल बन जाती है।

+0

सी में, हां। अक्सर सी ++ में मैं पहले एक टीएमपी समाधान की तलाश करूंगा। यह समझाने का कोई तरीका हो सकता है कि मैं सी –

+0

में अधिक उत्पादक क्यों हूं सी और सी ++ के बीच मेरी प्राथमिकता मैं जो कर रहा हूं उस पर निर्भर करती है, लेकिन मैं पूरी तरह से समझता हूं। –

1

सामान्य रूप से आप जो भी चाहते हैं उसे पूरा कर सकते हैं यदि आप सब कुछ एक मैक्रो में विलय करते हैं और फिर अपनी कक्षा को परिभाषित करने के लिए बूउस्ट प्रीप्रोसेसर लाइब्रेरी का लाभ उठाते हैं।देखें कि मैंने MACE_REFLECT मैक्रो को कैसे कार्यान्वित किया जो पूरे वर्ग का आंशिक विशेषज्ञता करता है और प्रत्येक नाम को अलग-अलग हिस्सों में दो बार संदर्भित करना चाहिए।

यह बहुत ही समान है कि मैं प्री-प्रोसेसर की सहायता से JSON को स्वचालित रूप से कैसे बना देता हूं।

अपने उदाहरण को देखते हुए, मैं इस तरह के रूप में यह अनुवाद होगा:

struct Name { 
    xyz_type xyz; 
    abc_type abc; 
    boost::optional<foo_type> foo; 
    boost::optional<bar_type> bar; 
}; 
MACE_REFLECT(Name, (xyz)(abc)(foo)(bar)) 

मैं अब 'यात्रा' मेरे पार्सर से नाम के सदस्यों कर सकते हैं:

struct visitor { 
    template<typename T, T p> 
    inline void operator()(const char* name)const { 
     std::cout << name << " = " << c.*p; 
    } 
    Name c; 
}; 
mace::reflect::reflector<Name>::visit(visitor()); 

अपने वस्तुओं के रूप में प्रतिनिधित्व किया जा सकता है structs, arrays, key-value-pair और primitives, तो यह तकनीक अद्भुत काम करती है और मुझे जेसन/एक्सएमएल या आपके कस्टम रिकॉर्ड प्रारूप से तत्काल क्रमबद्धता/deserializtion देता है।

https://github.com/bytemaster/mace/blob/master/libs/rpc/examples/jsonv.cpp

+0

अपनी शांत दुष्टता के लिए उपरोक्त, लेकिन, AFAICU (HYGWIMBTA = "आशा है कि मैं उस शब्द से क्या चाहता हूं"), वह दो बार फ़ील्ड नाम नहीं लिखना चाहता था। आपका संगीत मैक्रो को बस इतना चाहिए। –

संबंधित मुद्दे