2010-02-03 17 views
7

मैं एक कन्स्ट्रक्टर बना रहा हूं जो इनपुट इटरेटर्स की एक जोड़ी लेगा।मुझे टेम्पलेट फ़ंक्शन हस्ताक्षर में const_iterator semantics की आवश्यकता कैसे हो सकती है?

DataObject::DataObject(const char *begin, const char *end) 

हालांकि, मैं इस के किसी भी उदाहरण नहीं मिल सकता है: मैं विधि हस्ताक्षर संकलन समय const अर्थ विज्ञान के समान करना चाहते हैं।

template<class InputIterator> 
vector::vector(InputIterator first, InputIterator last) 
{ 
    construct(first, last, iterator_category(first)); 
} 

जो कोई संकलन समय const गारंटी देता है: उदाहरण के लिए, vector के लिए मेरे एसटीएल कार्यान्वयन की सीमा निर्माता के रूप में परिभाषित किया गया है। iterator_category/iterator_traits<> में const से संबंधित कुछ भी नहीं है।

क्या कॉलर की गारंटी देने का संकेत देने का कोई तरीका है कि मैं इनपुट डेटा को संशोधित नहीं कर सकता?

संपादित करें, 2010-02-03 16:35 यूटीसी

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

+0

क्या यह ऐसी चीज है जो संकलक-लागू अवधारणाओं के लिए अच्छा होगा? मुझे याद नहीं है कि प्रस्ताव ने कॉन्स आवश्यकताओं के बारे में कुछ भी कहा था। – mskfisher

+0

मुझे लगता है कि इस बिंदु पर सबसे अच्छा संभव विकल्प स्पष्ट रूप से 'कॉन्स्ट char *' का उपयोग करके फ़ंक्शन को तुरंत चालू करना है और अन्य सभी प्रकारों के लिए मेरे संकलन-समय की जांच के रूप में उस पर भरोसा करना है। – mskfisher

उत्तर

2

आप बस एक डमी समारोह जो char * const संकेत के साथ अपने टेम्पलेट कॉल बना सकते हैं। यदि आपका टेम्पलेट अपने लक्ष्यों को संशोधित करने का प्रयास करता है, तो आपका डमी फ़ंक्शन संकलित नहीं होगा। इसके बाद आप रिलीज बिल्ड से इसे बाहर करने के लिए #ifndef NDEBUG गार्ड के अंदर डमी डाल सकते हैं।

+0

यह इस तरह अधिक है। यह मुझे संकलन-समय आश्वासन देता है जिसे मैं ढूंढ रहा था। – mskfisher

+0

... हालांकि मेरे उद्देश्यों के लिए, मुझे लगता है कि आपका मतलब है 'कॉन्स्ट चार *' पॉइंटर्स। – mskfisher

+0

हां - दोह! बिल! –

2

क्या

के बारे में
#include <vector> 

template <class T> 
class MyClass{ 
public: 
    MyClass(typename T::const_iterator t1,typename T::const_iterator t2){ 
    } 
    // *EDITED*: overload for pointers (see comments) 
    MyClass(const T* t1,const T* t2){ 
    } 
}; 

void main(){ 
    std::vector<int> v; 
    std::vector<int>::const_iterator it1 = v.begin(); 
    std::vector<int>::const_iterator it2 = v.end(); 
    MyClass<std::vector<int> > mv(it1,it2); 

    // with pointers: 
    char* c1; 
    char* c2; 
    MyClass mc(c1,c2); 
} 
+0

आप आंतरिक प्रकारों का उपयोग करके टेम्पलेट पैरामीटर कटौती को रोकते हैं। –

+0

अच्छा विचार है, लेकिन मेरे पास यहां एक const_iterator नहीं है क्योंकि मैं दो 'char *' में iterators के रूप में गुजर रहा हूं। – mskfisher

+0

पॉइंटर्स की एक जोड़ी के लिए एक अधिभार जोड़ें। – UncleBens

0

वेक्टर निर्माता मूल्य द्वारा अपने तर्कों प्राप्त कर रहा है, जिसका अर्थ है कि फोन करने वाले का iterators निर्माता है, जो निश्चित रूप से इसका मतलब है कि कुछ भी नहीं है फोन करने वाले का iterators का क्या होता है में इस्तेमाल किया जा रहा से पहले कॉपी कर रहे हैं यही कारण है कि।

const इनपुट तर्कों के लिए केवल तभी महत्वपूर्ण है जब आप संदर्भ से गुज़र रहे हों। जैसे

void foo(int& x)

बनाम

void foo(const int& x)

पहले उदाहरण में, x के लिए फोन करने वाले का इनपुट foo द्वारा संशोधित किया जा सकता है। दूसरे उदाहरण में, ऐसा नहीं हो सकता है, क्योंकि संदर्भ const है।

+0

क्षमा करें, मैं अपने प्रश्न में पूरी तरह से स्पष्ट नहीं था। मैं यह सुनिश्चित करना चाहता हूं कि जिस डेटार इटेटरेटर इंगित कर रहे हैं उसे कॉन्स के रूप में माना जाने की गारंटी है, न कि इटरेटर स्वयं को आधार होना चाहिए। – mskfisher

+1

एक const_iterator का उपयोग कंटेनर के तत्व को संशोधित करने के लिए नहीं किया जा सकता है। एक सामान्य इटरेटर * उस तरह से उपयोग किया जा सकता है, भले ही यह कॉन्स्ट संदर्भ द्वारा पारित किया गया हो। (बस इसकी एक गैर-कॉन्स प्रति बनाएं।) 'Const iterator' और' const_iterator 'प्रकार समान चीज़ें नहीं हैं। –

9

कॉलर बस टेम्पलेट का उपयोग कॉन्स इटरेटर्स के साथ कर सकता है। यदि वह करता है, और संकलक शिकायत नहीं करता है, तो यह गारंटी दी जाती है कि फ़ंक्शन डेटा को संशोधित नहीं करता है। यदि यह डेटा को संशोधित करेगा, तो टेम्पलेट को एक कॉन्स इटरेटर के साथ त्वरित करने से त्रुटियों का कारण बन जाएगा।

आपको वास्तव में बल कॉलर को कॉन्स इटरेटर्स का उपयोग करने के लिए नहीं है क्योंकि आप कुछ भी संशोधित नहीं करते हैं।

+0

+1 ... और कहने के लिए मुझे यह इंगित करने की सभी परेशानी हो गई कि इसे कैसे किया जाए! –

+0

'डेटाऑब्जेक्ट' उदाहरण के अर्थशास्त्र का अर्थ है कि मैं गैर-'const' पॉइंटर्स में पास कर सकता हूं और उन्हें 'कॉन्स्ट' पॉइंटर्स के रूप में माना जा सकता है। मैं कॉलर को 'const' iterators का उपयोग करने के लिए मजबूर नहीं करना चाहता - मैं बस गारंटी देना चाहता हूं कि वे केवल * इस्तेमाल * * को 'const' iterators के रूप में उपयोग करेंगे। – mskfisher

+0

या तो आप डेटा की रक्षात्मक प्रतियां बनाते हैं, इसलिए यह नहीं बदलता है (आंतरिक कॉन्स char *), या आप अपनी आवश्यकताओं को दस्तावेज करते हैं और जीवन के साथ आगे बढ़ते हैं। – KitsuneYMG

0

यह वह जगह है आसान (लेकिन सुंदर) यदि आप बढ़ावा बर्दाश्त कर सकते हैं:

#include <boost/static_assert.hpp> 
#include <boost/type_traits.hpp> 

template<class It> 
void f(It b, It e) 
{ 
    using namespace boost; 
    typedef typename std::iterator_traits<It>::reference reference; 
    BOOST_STATIC_ASSERT(is_const<typename remove_reference<reference>::type>::value); 
} 

void test() 
{ 
    f((char const*)0, (char const*)0); // Compiles 
    f((char*)0, (char*)0); // Does not compile 
} 

संपादित: यदि आप अपने हस्ताक्षर में इस बारे में संकेत है और करना चाहते हैं तो यह के नाम का फायदा उठाने की आम है टेम्पलेट पैरामीटर:

template<class ConstIt> 
void f(ConstIt b, ConstIt e) 
... 
+1

जैसा कि मैं समझता हूं कि प्रश्न का बिंदु केवल यह सुनिश्चित करने के लिए है कि फ़ंक्शन स्वयं अनुक्रम को संशोधित नहीं कर सकता है। मुद्दा यह है कि उपयोगकर्ता को मैन्युअल रूप से चीजों को इस्टेटर्स को डालने के लिए मजबूर नहीं करना है। – UncleBens

+0

जैसा कि मैंने अपनी टिप्पणी में @sth में कहा था, मैं यह चाहता हूं कि इटेटरेटर को * कॉन्स्ट_इटरेटर के रूप में * इस्तेमाल किया जा सके, जैसे कि एक यादृच्छिक-पहुंच इटरेटर को अग्रेषित इटरेटर के रूप में उपयोग किया जा सके। – mskfisher

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

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