2012-12-20 21 views
17

मैं एक प्रोग्रामिंग समस्या को हल करने की कोशिश कर रहा हूं जिसमें ऑब्जेक्ट (इसे आरेख कहते हैं), जिसमें कई पैरामीटर शामिल हैं। प्रत्येक पैरामीटर (पैरामीटर वर्ग) कई प्रकारों में से एक हो सकता है: int, double, complex, string - कुछ नाम।टेम्पलेट सदस्य चर के साथ सी ++ कक्षा

तो मेरा पहला वृत्ति मेरे आरेख वर्ग को टेम्पलेट पैरामीटर के वेक्टर के रूप में परिभाषित करना था, जो इस तरह दिखेगा।

class Diagram 
{ 
private: 
    std::vector<Parameter<T> > v; 
}; 

यह संकलित नहीं होता है, और मैं समझता हूं क्यों। तो, यह पेज How to declare data members that are objects of any type in a class पर सिफारिशों के आधार पर, मैं अपने कोड को संशोधित तरह देखने के लिए:

class ParameterBase 
{ 
public: 
    virtual void setValue() = 0; 
    virtual ~ParameterBase() { } 
}; 


template <typename T> 
class Parameter : public ParameterBase 
{ 
public: 
    void setValue() // I want this to be 
        // void setValue(const T & val) 
    { 
     // I want this to be 
     // value = val; 
    } 

private: 
    T value; 
}; 

class Diagram 
{ 
public: 
    std::vector<ParameterBase *> v; 
    int type; 
}; 

मैं मुसीबत पता लगाना कैसे एक उपयुक्त टेम्प्लेट पैरामीटर के साथ setValue समारोह कॉल करने के लिए हो रही है। पैरामीटरबेस सार सारणी कक्षा में एक टेम्पलेटेड पैरामीटर होना संभव नहीं है। कोई भी मदद बहुत ही सराहनीय होगी।

पीएस मेरे पास boost :: किसी भी का उपयोग करने के लिए लचीलापन नहीं है।

+2

आप वस्तुतः, किसी भी मूल्य के लिए पैरामीटर सेट नहीं कर सकते हैं या तो उचित 'पैरामीटर ' प्रकार के कास्ट करने के लिए या वस्तु को हटाने और एक नया एक –

+3

बनाने एक सेटर का उपयोग न करें, एक निर्माता का उपयोग करें, तो जरूरत है आप हमेशा 'v.push_back (नया पैरामीटर (मेरा)) कर सकते हैं;' –

+1

क्यों न केवल उन्हें एक सामान्य प्रकार में परिवर्तित करें और आवश्यकता होने पर वापस परिवर्तित करें? इस तरह की चीजें आमतौर पर की जाती हैं। – KillianDS

उत्तर

25

आप बहुत करीब आ गए। मैं कुछ बिट्स जोड़ा क्योंकि वे काम

class ParameterBase 
{ 
public: 
    virtual ~ParameterBase() {} 
    template<class T> const T& get() const; //to be implimented after Parameter 
    template<class T, class U> void setValue(const U& rhs); //to be implimented after Parameter 
}; 

template <typename T> 
class Parameter : public ParameterBase 
{ 
public: 
    Parameter(const T& rhs) :value(rhs) {} 
    const T& get() const {return value;} 
    void setValue(const T& rhs) {value=rhs;}  
private: 
    T value; 
}; 

//Here's the trick: dynamic_cast rather than virtual 
template<class T> const T& ParameterBase::get() const 
{ return dynamic_cast<const Parameter<T>&>(*this).get(); } 
template<class T, class U> void ParameterBase::setValue(const U& rhs) 
{ return dynamic_cast<Parameter<T>&>(*this).setValue(rhs); } 

class Diagram 
{ 
public: 
    std::vector<ParameterBase*> v; 
    int type; 
}; 

आरेख तो इस तरह के सामान कर सकते हैं कर रहे हैं:

Parameter<std::string> p1("Hello"); 
v.push_back(&p1); 
std::cout << v[0]->get<std::string>(); //read the string 
v[0]->set<std::string>("BANANA"); //set the string to something else 
v[0]->get<int>(); //throws a std::bad_cast exception 

ऐसा लगता है कि अपने इरादे की तरह वेक्टर में संसाधन के मालिक संकेत स्टोर करने के लिए है। यदि ऐसा है, तो Diagram को सही विनाशक बनाने के लिए सावधान रहें, और इसे गैर प्रतिलिपि बनाने योग्य, और गैर-प्रति-असाइन करने योग्य बनाएं।

+1

आपके परीक्षण कोड में कुछ मामूली परिवर्तन करना था, लेकिन यह अच्छी तरह से काम करता है। धन्यवाद। – endbegin

+0

@endbegin: आपको क्या परिवर्तन करना पड़ा? अगर मुझे मेरे जवाब में त्रुटियां हैं, तो मैं उन्हें उन लोगों के लिए ठीक कर दूंगा जिनके पास भविष्य में समान समस्याएं हैं। –

+1

@endbegin: एक नोट के रूप में, यह लगभग बिल्कुल सही है कि ' boost :: any' works। –

3

बोले कार्यान्वयन कुछ सी ++ 11 फीचर्स का उपयोग करता है लेकिन आप उन्हें अलग करने में सक्षम होंगे।

#include <vector> 
#include <memory> 

class Parameter 
{ 
private: 
    class ParameterBase { 
    public: 
    virtual ~ParameterBase() {} 
    virtual ParameterBase* copy() = 0; 
    virtual void foo() = 0; 
    }; 

    template <typename T> 
    class ParameterModel : public ParameterBase { 
    public: 
    // take by value so we simply move twice, if movable 
    ParameterModel(const T& t) : t(t) {} 
    ParameterModel(T&& t) : t(t) {} 
    void foo() { t.foo(); } 
    ParameterModel* copy() { return new ParameterModel(*this); } 
    private: 
    T t; 
    }; 

public: 
    template <typename T> 
    Parameter(T&& t) 
    : pp(new ParameterModel< typename std::remove_reference<T>::type >(std::forward<T>(t))) {} 

    // Movable and Copyable only 
    Parameter(Parameter&&) = default; 
    Parameter& operator=(Parameter&&) = default; 

    Parameter(const Parameter& other) : pp(other.pp->copy()) {}; 
    Parameter operator=(const Parameter& other) { 
    pp.reset(other.pp->copy()); 
    return *this; 
    }; 

    // members 

    void foo() { pp->foo(); } 
private: 
    std::unique_ptr<ParameterBase> pp; 
}; 


class Diagram 
{ 
public: 
    std::vector<Parameter> v; 
    int type; 
}; 

struct X { 
    void foo() {} 
}; 

struct Y { 
    void foo() {} 
}; 

int main() 
{ 
    Diagram d; 
    d.v.emplace_back(X()); // int 

    // parameters are copyable and can be reassigned even with different 
    // impls 
    Parameter p = d.v.back(); 

    Parameter other((Y())); 
    other = p; 
    return 0; 
} 

यह कोड क्या करता है? यह इस तथ्य को छुपाता है कि हम अपने उपयोगकर्ताओं के लागू पैरामीटर को विरासत का उपयोग करते हैं। उन्हें केवल पता होना चाहिए कि हमें foo नामक एक सदस्य फ़ंक्शन की आवश्यकता है। ये आवश्यकताएं हमारे ParameterBase में व्यक्त की गई हैं। आपको इन आवश्यकताओं की पहचान करने की आवश्यकता है और ParameterBase पर जोड़ें। यह मूल रूप से एक और प्रतिबंधक boost::any है।

Sean Parent's value semantics बातचीत में वर्णित यह भी काफी करीब है।

+0

मुझे लगता है कि 'पैरामीटर' वर्ग की आवश्यकता नहीं है, और आप असाइनमेंट, पुन: असाइनमेंट करने या छिपे हुए डेटा पर जाने के लिए कोई (स्पष्ट) तरीका प्रदान नहीं करते हैं। :(लेकिन चूंकि आपके पास यह है, आपने इसे गैर-कॉम्पैक्टिव क्यों बनाया? –

+0

यह 'आरेख' में अस्थायी रूप से अस्थायी रूप से संदर्भित करने के लिए बहुत आसान बनाता है। – aschepler

+0

@aschepler धन्यवाद। मैंने कोडिंग के दौरान इसके बारे में सोचा। remove_reference'। – pmr

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

  • कोई संबंधित समस्या नहीं^_^