2010-04-12 13 views
18

एसटीएल आमतौर पर परिभाषित करता है तो जैसे एक निर्गम इटरेटर:आउटपुट इटरेटर के VALUE_TYPE

template<class Cont> 
class insert_iterator 
: public iterator<output_iterator_tag,void,void,void,void> { 
    // ... 

क्यों उत्पादन iterators value_typevoid के रूप में परिभाषित करते हैं? यह एल्गोरिदम के लिए उपयोगी होगा कि यह जानने के लिए कि किस प्रकार का मूल्य आउटपुट होना चाहिए।

उदाहरण के लिए, एक फ़ंक्शन जो यूआरएल क्वेरी "key1=value1&key2=value2&key3=value3" का अनुवाद किसी भी कंटेनर में करता है जिसमें कुंजी-मूल्य स्ट्रिंग तत्व होते हैं।

template<typename Ch,typename Tr,typename Out> 
void parse(const std::basic_string<Ch,Tr>& str, Out result) 
{ 
    std::basic_string<Ch,Tr> key, value; 
    // loop over str, parse into p ... 
     *result = typename iterator_traits<Out>::value_type(key, value); 
} 

SGI reference page of value_type संकेत यह है, क्योंकि यह एक आउटपुट इटरेटर भिन्नता के लिए संभव नहीं है। लेकिन उस value_type का ही उपयोग नहीं है: मैं आदेश इटरेटर निर्दिष्ट करने के लिए में एक दृष्टांत कर सकते हैं।

आउटपुट इटरेटर के साथ आउटपुट के लिए मूल्य बनाने के लिए क्या वैकल्पिक दृष्टिकोण है? दो दृष्टिकोण मैं माना:

  • एक functor पैरामीटर है कि सही प्रकार का ऑब्जेक्ट वापसी होगी स्वीकार करें। मैं अभी भी एल्गोरिदम का एक संस्करण चाहता हूं जो उस फ़ंक्शन ऑब्जेक्ट पैरामीटर को नहीं लेता है।
  • आवश्यकता होती है कि उत्पादन कंटेनर और कुछ एक प्रकार है कि से परिवर्तनीय pair<string,string> रखती है, या। मुझे आश्चर्य है कि मैं इस आवश्यकता के बिना कर सकता हूं, शायद किसी भी तत्व को दो std::string एस से बना सकता है।
+0

मुझे क्या करना कोशिश कर रहा हूँ एल्गोरिथ्म ऐसी है कि वह किसी भी प्रकार के कंटेनर है कि दो 'स्ट्रिंग' रों से निर्माण कर सकते हैं, न सिर्फ' नक्शा <स्ट्रिंग, स्ट्रिंग> 'साथ काम करता है सामान्य है। फिर, टेम्पलेट '* result = pair (key, value) 'के साथ-साथ' * result = unicorn_pony (key, value)' में तत्काल हो सकता है। – wilhelmtell

+0

यदि मैं एक संदर्भ जोड़ सकता हूं: आउटपुट इटरेटर के बारे में एक पेपर [पीडीएफ], इस मुद्दे के बारे में भी शिकायत करता है। http://semantics.org/publications/02_02_multiout.pdf – wilhelmtell

+1

उस पेपर में दिया गया उदाहरण बिल्कुल क्यों है कि आउटपुट इटरेटर्स को मूल्य प्रकार को परिभाषित करने की आवश्यकता नहीं है। उन्होंने मनमाने ढंग से निर्णय लिया कि 'मल्टीऑट :: value_type' 'डबल' होना चाहिए, लेकिन हकीकत में * किसी * प्रकार को जिसे' डबल 'और' int 'दोनों में रूपांतरित किया जा सकता है, असाइनमेंट ऑपरेटर के लिए उपयोग करने के लिए उचित मान हैं। –

उत्तर

7

इटरेटर का असली मूल्य प्रकार इटेटरेटर भी हो सकता है। operator* आसानी से सिर्फ इसलिए कि असली काम असाइनमेंट ऑपरेटर द्वारा किया जाता है *this के लिए एक संदर्भ वापस आ सकते हैं। आपको अच्छी तरह से पता चल सकता है कि *it = x; और it = x; आउटपुट इटरेटर्स के साथ बिल्कुल वही प्रभाव पड़ता है (मुझे लगता है कि बाद वाले को संकलित करने से रोकने के लिए विशेष उपाय किए जा सकते हैं)।

इस तरह, वास्तविक मूल्य प्रकार को परिभाषित करना उतना ही बेकार होगा। एक void के रूप में यह परिभाषित करना दूसरी तरफ, की तरह त्रुटियों को रोकने के कर सकते हैं:

typename Iter::value_type v = *it; //useless with an output iterator if it compiled 

मुझे लगता है यह सिर्फ उत्पादन iterators की अवधारणा की सीमा है: वे जिन वस्तुओं पर "दुरुपयोग" ऑपरेटर ओवरलोडिंग कर रहे हैं, के रूप में तो पॉइंटर जैसा दिखता है, जबकि वास्तव में कुछ पूरी तरह से अलग हो रहा है।

आपकी समस्या दिलचस्प है, हालांकि।आप किसी भी कंटेनर का समर्थन करना चाहते हैं, तो सवाल में उत्पादन iterators शायद std::insert_iterator, std::front_insert_iterator और std::back_insert_iterator होगा। इस मामले में आप निम्नलिखित की तरह कुछ कर सकता है:

#include <iterator> 
#include <vector> 
#include <string> 
#include <map> 
#include <iostream> 

//Iterator has value_type, use it 
template <class T, class IterValue> 
struct value_type 
{ 
    typedef IterValue type; 
}; 

//output iterator, use the container's value_type 
template <class Container> 
struct value_type<Container, void> 
{ 
    typedef typename Container::value_type type; 
}; 

template <class T, class Out> 
void parse_aux(Out out) 
{ 
    *out = typename value_type<T, typename Out::value_type>::type("a", "b"); 
} 

template <template <class> class Out, class T> 
void parse(Out<T> out) 
{ 
    parse_aux<T>(out); 
} 

//variadic template in C++0x could take care of this and other overloads that might be needed 
template <template <class, class> class Out, class T, class U> 
void parse(Out<T, U> out) 
{ 
    parse_aux<T>(out); 
} 

int main() 
{ 
    std::vector<std::pair<std::string, std::string> > vec; 
    parse(std::back_inserter(vec)); 
    std::cout << vec[0].first << ' ' << vec[0].second << '\n'; 

    std::map<std::string, std::string> map; 
    parse(std::inserter(map, map.end())); 
    std::cout << map["a"] << '\n'; 

    //just might also support normal iterators 
    std::vector<std::pair<std::string, std::string> > vec2(1); 
    parse(vec2.begin()); 
    std::cout << vec2[0].first << ' ' << vec2[0].second << '\n'; 
} 

यह अभी भी सिर्फ तुम इतनी दूर मिलेगा। मुझे लगता है कि कोई इसे आगे ले सकता है, इसलिए यह std::ostream_iterator<printable_type> का प्रबंधन भी कर सकता है, लेकिन किसी बिंदु पर यह इतना जटिल हो जाएगा कि त्रुटि संदेश को समझने के लिए भगवान को ले जाता है, कुछ गलत होना चाहिए।

2

एक पुनरावर्तक के value_type का उद्देश्य उस प्रकार को परिभाषित करना है जब उस इटरेटर को संदर्भित किया जाता है। *output_iterator = value के रूप में - उत्पादन iterators के लिए, भिन्नता ऑपरेटर का केवल वैध का उपयोग जब यह असाइनमेंट ऑपरेटर के साथ संयोजन के रूप में इस्तेमाल किया जाता है। आउटपुट इटरेटर को डिफ्रेंस करते समय लौटाया जाने वाला प्रकार आवश्यक रूप से उन प्रकारों के साथ कोई सीधा संबंध नहीं रखता है जिन्हें आउटपुट इटरेटर के माध्यम से संग्रहीत किया जा सकता है। एकमात्र आवश्यक रिश्ते यह है कि बाद के प्रकार को पूर्व प्रकार के लिए असाइन करने का कोई तरीका है।

इसके अलावा, आउटपुट इटरेटर कई प्रकार के मानों को स्टोर कर सकता है, और इन प्रकारों को एक दूसरे के साथ कोई संबंध नहीं होना चाहिए। उदाहरण null_output_iteratorDiscarding the output of a function that needs an output iterator में वर्णित के लिए ले लो। यह इटरेटर किसी भी प्रकार के मूल्य भंडारण के लिए स्वीकार कर सकता है।

+0

जब आप कहते हैं कि _, _ "पुनरावर्तक के VALUE_TYPE के प्रयोजन के प्रकार है कि जब कि इटरेटर dereferenced है लौटा दिया जाता है परिभाषित करने के लिए है" आपको लगता है कि के लिए संदर्भ निर्दिष्ट करें कर सकते हैं? मानक में एक शब्द, शायद? मानक के खंड 24.3.1 में मुझे 'value_type' के लिए कोई विवरण नहीं है, केवल आउटपुट इटरेटर इसे शून्य पर सेट कर सकते हैं। टीसीपीएल 3e में, धारा 1 9 .2.2, स्ट्रॉस्ट्रप कहता है कि केवल "' value_type' तत्व का प्रकार है "। – wilhelmtell

+0

मानक की धारा 24.1 से, "सभी iterators मैं अभिव्यक्ति का समर्थन करते * मैं, कुछ वर्ग, गणन के एक मूल्य है, जिसके परिणामस्वरूप या निर्मित प्रकार टी, इटरेटर का मान प्रकार कहा जाता है।" खंड 24.3.1 से, "[...] यह आवश्यक है कि अगर इटरेटर पुनरावर्तक के प्रकार है, [...] iterator_traits :: VALUE_TYPE के रूप में इटरेटर के [...] मान प्रकार [परिभाषित किया जा ...]। " इसके अलावा खंड 24.3.1 से, "एक निर्गम इटरेटर के मामले में, [...] iterator_traits :: VALUE_TYPE [... है ...] शून्य के रूप में परिभाषित।" –

+1

ठीक है, मुझे पता है कि आउटपुट इटरेटर्स के पास 'value_type'' void' पर सेट है। 'I'' 'i' के' value_type' होने के साथ, और प्रोग्रामर को 'i' को अस्वीकार करने की अनुमति नहीं है, फिर भी' i i' 'शून्य 'होने की अनुमति देने में एक छलांग है। इसे 'शून्य' की आवश्यकता नहीं है। 'Value_type' के लिए अन्य, वैध उपयोग हैं। मैं इस पर बहस नहीं कर रहा हूं, मैं सिर्फ आउटपुट इटरेटर के 'value_type' को 'void'' में परिभाषित करने के लिए" आउटपुट इटरेटर को अपमानित नहीं कर सकता "से छलांग को समझ नहीं पा रहा हूं। – wilhelmtell

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