2008-11-16 8 views
5

मेरे पास वेक्टर-जैसी कक्षा है जिसमें "T" प्रकार की ऑब्जेक्ट्स की एक सरणी है, और मैं 4 अंकगणितीय ऑपरेटरों को कार्यान्वित करना चाहता हूं, जो प्रत्येक आइटम पर ऑपरेशन लागू करेंगे:सी ++: फ़ंक्शन ऑब्जेक्ट के रूप में दो आंतरिक प्रकारों के ऑपरेटर का उपयोग

// Constructors and other functions are omitted for brevity. 
template<class T, unsigned int D> 
class Vector { 

public: 
    // Add a value to each item: naive implementation. 
    void operator += (const T&) { 
     for (int i = 0; i < D; ++i) { 
      data[i] += value; 
     } 
    } 
    void operator -= (const T&) { ... } 
    void operator *= (const T&) { ... } 
    void operator /= (const T&) { ... } 

private: 
    T items[D]; 
}; 

क्योंकि ऑपरेटरों एक ही बॉयलरप्लेट कोड में शामिल होंगे (हर तत्व पर पाशन और उचित संचालन को लागू करने), मैंने सोचा कि मैं यह सामान्य हो सकते हैं:

template<class T, unsigned int D> 
class Vector { 

public: 
    void operator += (const T& value) { do_for_each(???, value); } 
    void operator -= (const T& value) { do_for_each(???, value); } 
    void operator *= (const T& value) { do_for_each(???, value); } 
    void operator /= (const T& value) { do_for_each(???, value); } 

private: 
    void 
    do_for_each(std::binary_function<void, T, T>& op, T value) { 
     std::for_each(data, data + D, std::bind2nd(op, value)); 
    } 

    T data[D]; 
}; 

अब, समस्या यह है, मैं कैसे पारित करना एक ऑपरेटर जो दो intrins लेता है आईसी प्रकार और void से do_for_each लौटाता है, जैसा ऊपर उपरोक्त उदाहरण में दिखाया गया है? सी ++ मुझे आंतरिक प्रकार के लिए यह चाल (यदि "T""int" है "T::operator+=" काम नहीं करेगा) करते हैं नहीं है।

+0

आप 'ठीक करने के लिए डेटा' बनाम' items' ... – Alastair

+0

धन्यवाद, फिक्स्ड चाहते हो सकता है यह भी नीचे –

+0

इस तरह के प्रश्न हैं कि दोस्त दोस्तों को ओवरलोड ऑपरेटर – Jonathan

उत्तर

8

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

इसके अलावा, आपके do_for_each एक टेम्पलेट होने के लिए है, क्योंकि यह समारोह वस्तु की सटीक प्रकार पता करने के लिए है, के रूप में द्विआधारी समारोह वस्तुओं polymorph कक्षाएं नहीं हैं। वास्तविक ऑपरेशन के लिए, आप std::transform उपयोग करना चाहते हैं:

template<class T, unsigned int D> 
class Vector { 

public: 
    Vector& operator += (const T& value) { 
     do_for_each(std::plus<T>(), value); 
     return *this; 
    } 

    Vector& operator -= (const T& value) { 
     do_for_each(std::minus<T>(), value); 
     return *this; 
    } 

    Vector& operator *= (const T& value) { 
     do_for_each(std::multiplies<T>(), value); 
     return *this; 
    } 

    Vector& operator /= (const T& value) { 
     do_for_each(std::divides<T>(), value); 
     return *this; 
    } 

private: 
    template<typename BinFun> 
    void do_for_each(BinFun op, const T& value) { 
     std::transform(data, data + D, data, std::bind2nd(op, value)); 
    } 

    T data[D]; 
}; 

std::transform सिर्फ समारोह वस्तु के लिए प्रत्येक तत्व पारित करेंगे, और परिणाम तीसरा तर्क के रूप में दिया इटरेटर को वापस प्रदान करती है।

+0

नहीं देते हैं, मैं बस एक ही चीज़ लिखने की प्रक्रिया में था! :) चीयर्स, +1! (V + = v2) - = v3 –

+0

आप ऑपरेटरों से एक स्थिरांक संदर्भ लौट जाना चाहिए, ताकि यह कर (जो वास्तव में पढ़ने के लिए कठिन है/यह पता लगाने) संभव नहीं है मैं करने के लिए विशेष कारणों से नहीं दिख रहा है इसे मना करो। साथ ही, जब आप गैर-कॉन्स वापस करते हैं, तो आप ऐसा करते हैं जो अधिकतर नहीं करते हैं। यह कम से कम आश्चर्य के सिद्धांत के खिलाफ प्रयास करता है। यह एफ (ए + = बी) करने के लिए पूरी तरह से उचित है; उदाहरण के लिए। – SoapBox

+0

सोपबॉक्स: –

2

आपको वास्तव में Boost Operators पर एक नज़र रखना चाहिए, एक हेडर-केवल लाइब्रेरी जो वास्तव में ऑर्थोगोनल और लगातार अंकगणितीय ऑपरेटर ओवरलोड बनाने में सरल बनाती है।

विशेष रूप से: आपको पता चल सकता है कि boost::operators::integer_arithmatic<T> से पाने आप इस वर्ग की पुनरावृत्ति का एक बहुत बचाता है।

1

मुझे लगता है कि litb सही रास्ते पर है और सही प्रश्न का जवाब दे दिया।
लेकिन मुझे लगता है कि यह गलत समाधान है।

मैं नहीं बल्कि do_for_each() का उपयोग नहीं होता बल्कि एसटीडी का उपयोग :: बदलने() सीधे:

template<class T, unsigned int D> 
class Vector 
{ 

    public: 
    Vector& operator += (const T& value) { 
     std::transform(data, data + D, data, std::bind2nd(std::plus<T>(),value)); 
     return *this; 
    } 

    Vector& operator -= (const T& value) { 
     std::transform(data, data + D, data, std::bind2nd(std::minus<T>(),value)); 
     return *this; 
    } 

    Vector& operator *= (const T& value) { 
     std::transform(data, data + D, data, std::bind2nd(std::multiplies<T>(),value)); 
     return *this; 
    } 

    Vector& operator /= (const T& value) { 
     std::transform(data, data + D, data, std::bind2nd(std::divides<T>(),value)); 
     return *this; 
    } 

    private: 
    T data[D]; 
}; 
संबंधित मुद्दे