2013-02-12 40 views
26

This SO questionstd::generate और मानक द्वारा की गई गारंटीओं के बारे में एक चर्चा को जन्म दिया। विशेष रूप से, क्या आप आंतरिक स्थिति वाले फ़ंक्शन ऑब्जेक्ट्स का उपयोग कर सकते हैं और generate(it1, it2, gen) पर gen() पर कॉल करने के लिए भरोसा कर सकते हैं, परिणाम *it पर संग्रहीत करें, gen() पर कॉल करें, *(it + 1) आदि में स्टोर करें, या उदाहरण के लिए, क्या यह पीछे से शुरू हो सकता है?सी ++ मानक शब्द: क्या "सीमा में सभी इटरेटर के माध्यम से" अनुक्रमिकता का अर्थ है?

मानक (n3337, §25.3.7/1) इस कहते हैं:

प्रभाव: पहले एल्गोरिथ्म समारोह वस्तु gen invokes और सीमा [first,last) में सभी iterators के माध्यम से जनरल की वापसी मान नियत । दूसरा एल्गोरिदम फ़ंक्शन ऑब्जेक्ट जेन को आमंत्रित करता है और [first,first + n) श्रेणी में सभी पुनरावृत्तियों के माध्यम से जेन का रिटर्न वैल्यू असाइन करता है यदि n सकारात्मक है, अन्यथा यह कुछ भी नहीं करता है।

ऐसा लगता है कि कोई आदेश देने की गारंटी दी गई है, खासकर जब से अन्य पैराग्राफ मजबूत शब्दों है, उदाहरण के लिए std::for_each (प्रभाव:, सीमा [first,last) में हर इटरेटर अपसंदर्भन पहले से शुरू और last - 1 के लिए आगे बढ़ने के परिणाम के f लागू होता है यदि हम इसे सचमुच ले रहे हैं, तो यह केवल first से शुरू होने की गारंटी देता है और last पर समाप्त होता है - हालांकि आदेश में कोई गारंटी नहीं है)।

लेकिन: दोनों Microsoft's और Apache's C++ standard library दोनों अपने में ऐसे कई पृष्ठ है कि मूल्यांकन की आवश्यकता होती अनुक्रमिक होने के लिए पर उदाहरण दे। और libC++ (algorithm में) और libstdC++ (bits/stl_algo.h में) इसे इस तरह कार्यान्वित करें। इसके अलावा, आप इस गारंटी के बिना generate के लिए बहुत से संभावित एप्लिकेशन खो देते हैं।

क्या वर्तमान शब्द अनुक्रमिकता दर्शाता है? यदि नहीं, तो क्या यह समिति के सदस्यों या जानबूझकर पर्यवेक्षण था?

(मुझे अच्छी तरह से पता है कि ऐसे कई लोग नहीं हैं जो इस प्रश्न के अंतर्दृष्टिपूर्ण उत्तर प्रदान कर सकें, केवल अटकलों या चर्चा के बिना, लेकिन मेरी विनम्र राय में, यह एसओ दिशानिर्देशों के अनुसार यह प्रश्न 'रचनात्मक नहीं' बना देता है ।)


धन्यवाद इस मुद्दे ओर इशारा करते हुए और मुझे for_each के बारे में पैरा की चर्चा करते हुए के लिए @juanchopanza करने के लिए।

+1

मुझे नहीं लगता कि 'उत्पन्न()' बहुत उपयोगी अगर यह अनुक्रमिक नहीं है। –

+8

मेरा मानना ​​है कि आवश्यक इटरेटर * कक्षा * के संदर्भ में लिया जाने पर अस्पष्टता काफी उठाई जाती है * टेम्पलेट फ़ंक्शन को प्रदान किया जाना आवश्यक है; ** 'टेम्पलेट <वर्ग फॉरवर्डइटरेटर, क्लास जनरेटर>' **। चूंकि पहले और आखिरी दोनों ही अग्रेषित हैं, केवल उन्हें सरणी या वेक्टर निर्माण में ढेर करने के लिए सहेजें, फिर अनुक्रमिक रूप से अनुक्रम के बारे में छलांग लगाने के लिए, आपके पास शुरुआत में शुरू करने के लिए बहुत कम विकल्प है, और अंत में पहुंचें। – WhozCraig

+0

@WozozCraig हे, मैं पूरी तरह से याद किया। मेरी राय में, यह एक अंतर्दृष्टिपूर्ण उत्तर है और आपको इसे इस तरह पोस्ट करना चाहिए। फिर भी, मैं इस पर समिति या पुस्तकालय कार्यान्वयन के करीब लोगों से उनके विचारों के बारे में सुनना चाहता हूं। – us2012

उत्तर

7

LWG475, std::for_each की चर्चा में std::transform के साथ तुलना की जाती है। यह नोट किया गया है कि "transform उस ऑर्डर की गारंटी नहीं देता है जिसमें उसकी फ़ंक्शन ऑब्जेक्ट कहा जाता है"। तो, हां, समिति मानक में अनुक्रमिक गारंटी की कमी से अवगत है।

गैर अनुक्रमिक व्यवहार के लिए कोई विपरीत आवश्यकता नहीं है, इसलिए माइक्रोसॉफ्ट और अपाचे अनुक्रमिक मूल्यांकन का उपयोग करने के लिए स्वतंत्र हैं।

+0

बहुत रोचक (अगर कुछ हद तक परेशान है, क्योंकि विशेष रूप से 'जेनरेट'/'जेनरेशन' के लिए मुझे लगता है कि अनुक्रमिक व्यवहार को संभावित दोषों से कहीं अधिक दूर करने के लाभ)। धन्यवाद! – us2012

5

कहीं भी मानक एल्गोरिदम पर ऑर्डरिंग निर्दिष्ट नहीं करता है, आपको यह मानना ​​चाहिए कि एक कार्यान्वयन समानांतरता के लिए इसका फायदा उठा सकता है। पेपर n3408 समांतरता के लिए विकल्पों पर चर्चा करता है, और Thrust लाइब्रेरी को इंगित करता है, जो मानक एल्गोरिदम के उपयोग योग्य समानांतर-सक्षम पुनर्मूल्यांकन और एल्गोरिदम में समांतरता के भविष्य के मानकीकरण के लिए सबूत-अवधारणा दोनों है।

generate के जोर के कार्यान्वयन को देखते हुए, यह समांतर लूप में gen पर कॉल करता है जब भी इटरेटर श्रेणी यादृच्छिक पहुंच होती है। जैसा कि आपने देखा है, यह मानक के अनुरूप है, इसलिए आपको यह नहीं मानना ​​चाहिए कि generate हमेशा अनुक्रमिक होगा। (उदाहरण के लिए, एक धागा सुरक्षित std::rand कुशलतापूर्वक generate के साथ प्रयोग किया जा सकता है और अनुक्रमिक मंगलाचरण आवश्यकता नहीं है।)

केवल एल्गोरिदम कि अनुक्रमिक मंगलाचरण की गारंटी numeric में होते हैं; यदि आपका कोड अनुक्रमिक आमंत्रण पर निर्भर करता है, तो आपको के स्थान पर iota का उपयोग करना चाहिए।

template<typename F> struct iota_adapter { 
    F f; 
    operator typename std::result_of<F()>::type() { return f(); } 
    void operator++() {} 
}; 
template<typename F> iota_adapter<F> iota_adapt(F &&f) { return {f}; } 

उपयोग के रूप में: एक मौजूदा जनरेटर अनुकूल

#include <numeric> 
#include <iostream> 

int main() { 
    int v[5], i = 0; 
    std::iota(std::begin(v), std::end(v), iota_adapt([&i]() { return ++i; })); 
    for (auto i: v) std::cout << i << '\n'; 
} 
+1

दिलचस्प! काफी हद तक, जोरदार लेखक 'std :: gener' के लिए अनुक्रमिकता मानते हैं: http: //thrust.github पर कोड उदाहरणों को देखते हुए।कॉम /, वे 'std :: gener' का उपयोग करते हैं और ऊपर दी गई टिप्पणी कहती है "क्रमशः 32 एम यादृच्छिक संख्याएं उत्पन्न करें"। 'iota' हालांकि एक असंतुष्ट विकल्प है, इसके लिए आवश्यक है कि रिटर्न प्रकार में 'ऑपरेटर ++' हो जो आप चाहते हैं। मुझे लगता है कि एक 'seq_generate' अपने आप को कार्यान्वित करना सबसे अच्छा समाधान हो सकता है, यह देखते हुए कि यह करना मुश्किल नहीं है। – us2012

+0

मैं इसे समानांतर में विरोध के रूप में "क्रमशः" के रूप में पढ़ूंगा (क्योंकि 'std :: rand' अनुक्रमिकता को लागू करने के बजाय समानांतर-जागरूक या -साई नहीं हो सकता है)। 'Iota' को अनुकूलित करना बहुत मुश्किल नहीं है; मैं एक उदाहरण प्रदान करूंगा। – ecatmur

+0

दो छोटी टिप्पणियां: 1) 5 एल्गोरिदम फॉर्म '': 'for_each',' copy', 'copy_backward',' move' और 'move_backward' अनुक्रमिक भी हैं। 2) 'iota' के लिए अनुक्रमिकता गारंटी के लिए शब्द अजीब एक है, क्योंकि यह "क्रम में" वाक्यांश का उपयोग नहीं करता है बल्कि "++ मान के रूप में वृद्धि मूल्य" का उपयोग नहीं करता है। – TemplateRex

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