2010-09-08 11 views
10

जहां तक ​​मैं समझता हूँ, वहाँ (, boost::serialization वास्तव में) कोई क्रमबद्धता है boost::any प्लेसहोल्डर के लिए समर्थन करते हैं।सी ++ - बढ़ावा :: किसी भी क्रमबद्धता

कोई पता है अगर वहाँ एक कस्टम boost::any इकाई क्रमानुसार करने के लिए एक रास्ता है?

समस्या यहाँ स्पष्ट है: boost::any टेम्पलेट आधारित प्लेसहोल्डर का उपयोग करता है वस्तुओं को स्टोर करने और यदि boost::any_cast उचित है typeid जाँच करने के लिए।

तो, वहाँ एक कस्टम सार सुपर क्लास placeholder और कस्टम टेम्पलेट आधारित व्युत्पन्न वर्ग है, जो निम्न प्रकार से बनाई गई हैं है:

template <T> custom_placeholder : public placeholder { 
    virtual std::type_info type() const { return typeid(T); } 
    virtual ... 
}; 

जाहिर है, यह कुछ मुसीबतों लाता है जब भी इस चीज serializing के बारे में सोच। शायद किसी को इस तरह के क्रमबद्धरण (और निश्चित रूप से, उचित deserialization) बनाने के लिए कुछ चाल पता है?

धन्यवाद

उत्तर

5

संभव नहीं सब पर, कम से कम मनमाना प्रकार के लिए है। ध्यान दें कि हो सकता है आप (किसी भी में निहित तत्वों का आकार खोजने की तरह) कुछ मुश्किल कोड का उपयोग कर क्रमानुसार सकता है, लेकिन किसी भी कोड संकलक स्थिर प्लेसहोल्डर के अंदर किसी भी type_code और उचित प्रकार डाल पर निर्भर करता है। आप निश्चित रूप से सी ++ में deserialization में ऐसा नहीं कर सकते हैं, क्योंकि जिस तरह से आप deserialization से प्राप्त करेंगे, संकलन समय पर ज्ञात नहीं है (जैसा कि नव निर्मित boost::any द्वारा आवश्यक है)।

सबसे अच्छा समाधान तत्वों आप क्रमानुसार करने जा रहे हैं की सही प्रकार के लिए किसी भी प्रकार के विशेष किसी तरह का निर्माण करना है। फिर, आपके पास वास्तविक प्रकार के तत्व को deserialized के लिए विशेष मामले हो सकते हैं, लेकिन ध्यान दें कि प्रत्येक तत्व प्रकार क्रमिकरण/deserialization स्थिर सी ++ कोड के रूप में भौतिक रूप से लिखा जाना है।

पीडी। कुछ अन्य ने इस विशेष प्रकार के प्रतिनिधित्व के रूप में boost::variant का उपयोग करने का सुझाव दिया है, जिसे आप सटीक प्रकारों को क्रमबद्ध करने जा रहे हैं। आपको deserialization पर सटीक प्रकार समझने का एक तरीका चाहिए, हालांकि (शायद संस्करण में प्रकारों के लिए पहचानकर्ता असाइन करना)।

+0

प्रकारों के एक ज्ञात सेट के लिए एक विशेष प्रकार को एक प्रकार कहा जाता है जैसे उदा। ['boost :: variant'] (http://www.boost.org/doc/libs/1_44_0/doc/html/variant.html) (जो स्पष्ट रूप से केवल नींव देता है)। –

+0

@ जॉर्ज: हाँ, संकेत के लिए धन्यवाद। मैंने इसे प्रतिबिंबित करने के लिए प्रतिक्रिया संपादित की। –

1

मान लें कि आपको boost::any का उपयोग करना है और आप variant पर स्विच नहीं कर सकते हैं, map<type_info const*, string(*)(any)> आधारित समाधान आपको पूरा कर सकता है।

आपको रनटाइम पर ऐसे map पर प्रारंभ करना होगा, जिनकी आप उपयोग करने की योजना बना रहे हैं। बेशक, आप

template <typename T> 
struct any_serializer 
{ 
    static string perform(any a) 
    { 
     T const& x = any_cast<T const&>(a); 
     stringstream out; 
     out << x; 
     return out.str(); 
    } 
}; 

की तर्ज पर कुछ का उपयोग करें और कुंजी &typeid(T) तहत any_serializer<T>::perform के पते के साथ नक्शे को पॉप्युलेट कर सकते हैं। आप कक्षा any_serializer श्रेणी का विशेषज्ञ कर सकते हैं और मानचित्र को पॉप्युलेट करने के लिए कुछ (बदसूरत) मैक्रोज़ का उपयोग कर सकते हैं।

अधिक मुश्किल निश्चित रूप से अक्रमांकन है। मैंने थोड़ी देर के लिए boost::lexical_cast पर एक नज़र डाली है, शायद यह कुछ मदद प्रदान कर सकती है। मुझे डर है कि यह पूरी तरह से समस्या-निर्भर है। हालांकि, आपको केवल एक फ़ंक्शन की आवश्यकता है, जो string लेता है और एक any देता है। आप कस्टम आउटपुट पहचानकर्ता के साथ अपनी आउटपुट स्ट्रिंग को भी प्रीपेड करना चाह सकते हैं। अपनी खुद की

+1

यह स्कीमा बल्कि मुश्किल है, और अगर यह कहें, तो आप उन प्रक्रियाओं को नेट पर अन्य प्रक्रिया या कंप्यूटर पर भेज देंगे। ध्यान दें कि 'और टाइपिड (टी)' विभिन्न आर्किटेक्चर (और यहां तक ​​कि प्रोग्राम भी) के लिए अलग होंगे, इसलिए मुझे यह बहुत विश्वसनीय नहीं लगता है ... प्रतिक्रिया के बाद संपादित करें: हां, यह कस्टम प्रकार पहचानकर्ता का उपयोग करके अधिक समझ में आता है। प्रतिबंधित प्रकारों के सेट के साथ संस्करण का उपयोग करना भी एक अच्छा विचार है। –

+0

@ डिएगो: मुझे समस्या नहीं दिखाई दे रही है। नक्शा कार्यक्रम के लिए स्थानीय है और विभिन्न धारावाहिक दिनचर्या भेजने के लिए केवल एक माध्यम है। मैं इस बारे में अधिक चिंतित हूं कि क्या 'टाइपिड (टी) हमेशा ऑब्जेक्ट्स उत्पन्न करता है जिसे पते से तुलना की जा सकती है। इसे एक साधारण रैपर वर्ग के साथ हल किया जा सकता है जो 'type_info :: पहले 'ऑपरेटर <' के रूप में' कॉल करता है। –

+0

@Alexandre: मैं नेटवर्क चैनल के माध्यम से मानचित्र (टाइपिड की चाबियों का उपयोग करके) को स्थानांतरित करने के लिए प्रतिबिंबित कर रहा था, उदाहरण के लिए, या विभिन्न आर्किटेक्चर या ऑपरेटिंग सिस्टम में चल रहे विभिन्न अनुप्रयोगों द्वारा पढ़ा जा रहा था। मानचित्र के लिए यह कुंजी प्रोग्राम-निर्भर होगी, और आपको एक सिस्टम-स्वतंत्र प्रकार पहचानकर्ता की आवश्यकता होगी, जैसा कि आपने प्रतिक्रिया में आपके संपादन में जोड़ा था। –

6

आप को बढ़ावा देने के साथ रहना चाहते हैं :: किसी भी मुझे यकीन नहीं कर रहा हूँ, लेकिन आप लिख सकते हैं "को बढ़ावा देने :: किसी भी"। मैं पैरामीटर को पारित करने के लिए प्रॉक्सी विधियों के लिए इस कोड का उपयोग कर रहा हूँ।

#include <iostream> 
#include <boost\smart_ptr\scoped_ptr.hpp> 
#include <boost/shared_ptr.hpp> 
#include <boost/serialization/access.hpp> 
#include <boost/serialization/shared_ptr.hpp> 
#include <boost/archive/text_oarchive.hpp> 
#include <boost/archive/text_iarchive.hpp> 
#include <boost/serialization/export.hpp> 
#include <sstream> 
class my_placeholder 
{ 
public: 
    virtual ~my_placeholder(){} 
    my_placeholder(){} 
private: 
    friend class boost::serialization::access; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     // serialize base class information 
     //ar & boost::serialization::base_object<bus_stop>(*this); 
     //ar & m_placeholder; 

    } 

}; 




template<typename T> 
class my_derivedplaceholder: 
    public my_placeholder 
{ 
    public: 
     my_derivedplaceholder() 
     { 

     } 
     my_derivedplaceholder(T &value) 
     { 
      m_value=value; 
     } 
    T m_value; 

private: 
    friend class boost::serialization::access; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     // serialize base class information 
     ar & boost::serialization::base_object<my_placeholder>(*this); 
     ar & m_value; 

    } 
}; 


BOOST_CLASS_EXPORT_GUID(my_derivedplaceholder<int>, "p<int>"); 


class my_any 
{ 
public: 

    my_any() 
    { 

    } 

    template<typename T> 
    my_any(const T &value) 
    { 
     m_placeholder.reset(new my_derivedplaceholder<T>(const_cast<T&>(value))); 
    } 

    template<typename T> 
    void operator=(const T &value) 
    { 
     m_placeholder.reset(new my_derivedplaceholder<T>(const_cast<T&>(value))); 
    } 



protected: 

    friend class boost::serialization::access; 
    template<class Archive> 
    void serialize(Archive & ar, const unsigned int version) 
    { 
     // serialize base class information 
     //ar & boost::serialization::base_object<bus_stop>(*this); 
     ar & m_placeholder; 

    } 

    template<typename T> 
    friend T my_anycast(my_any &val); 

    boost::shared_ptr<my_placeholder> m_placeholder; 
}; 

template<typename T> 
T my_anycast(my_any &val) 
{ 
    boost::shared_ptr<my_derivedplaceholder<T>> concrete=boost::dynamic_pointer_cast<my_derivedplaceholder<T>>(val.m_placeholder); 
    if (concrete.get()==NULL) 
     throw std::invalid_argument("Not convertible"); 

    return concrete->m_value; 
} 

void main() 
{ 
    my_any m=10; 

    int a=my_anycast<int>(m); 

    std::cout << a << std::endl; 

    std::stringstream ss,ss2; 
    boost::archive::text_oarchive oa(ss); 

    oa << m; 

    boost::archive::text_iarchive ia(ss); 

    my_any m2; 
    ia >> m2; 

    std::cout << my_anycast<int>(m2) << std::endl; 
} 
1

नई कक्षा बनाने की कोई आवश्यकता नहीं है। Xany https://sourceforge.net/projects/extendableany/?source=directory का उपयोग करने का प्रयास करें xany क्लास किसी भी मौजूदा कार्यक्षमता में नए तरीकों को जोड़ने की अनुमति देता है। वैसे भी दस्तावेज़ीकरण में एक उदाहरण है जो वही करता है जो आप चाहते हैं।

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