2017-08-08 16 views
5

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

मैंने इस कोड को gcc 7.1.0 के साथ संकलित करने का प्रयास किया है।

फ़ाइल test.cpp

#include <vector> 
#include <type_traits> 
#include <typeinfo> 

template <typename Iterator> 
using traits = typename std::iterator_traits<Iterator>::iterator_category; 

template <typename T> 
class A{ 
    private: 

     std::vector<T> v; 

    public: 

     template <typename InputIterator, 
       typename = std::enable_if_t< 
        typeid(traits<InputIterator>) == 
        typeid(std::input_iterator_tag)> 
       > 
     A(InputIterator first, InputIterator last) : v(first, last) {} 
}; 

int main(){ 
    std::vector<double> v = {1, 2, 3, 4, 5}; 
    A<double> a(v.begin(), v.end()); 
} 

मैं g++ test.cpp -o test के साथ इस संकलन त्रुटि मिलती है:

test.cpp: In function ‘int main()’: 
    test.cpp:27:34: error: no matching function for call to ‘A<double>::A(std::vector<double>::iterator, std::vector<double>::iterator)’ 
     A<double> a(v.begin(), v.end()); 
            ^
    test.cpp:22:7: note: candidate: template<class InputIterator, class> A<T>::A(InputIterator, InputIterator) 
     A(InputIterator first, InputIterator last) : v(first, last) {} 
     ^
    test.cpp:22:7: note: template argument deduction/substitution failed: 
    test.cpp: In substitution of ‘template<bool _Cond, class _Tp> using enable_if_t = typename std::enable_if::type [with bool _Cond = ((const std::type_info*)(& _ZTISt26random_access_iterator_tag))->std::type_info::operator==(_ZTISt18input_iterator_tag); _Tp = void]’: 
    test.cpp:18:16: required from here 
    test.cpp:19:49: error: call to non-constexpr function ‘bool std::type_info::operator==(const std::type_info&) const’ 
        typeid(traits<InputIterator>) == 
    test.cpp:18:16: note: in template argument for type ‘bool’ 
        typename = std::enable_if_t< 
        ^~~~~~~~ 
    test.cpp:10:7: note: candidate: A<double>::A(const A<double>&) 
    class A{ 
     ^
    test.cpp:10:7: note: candidate expects 1 argument, 2 provided 
    test.cpp:10:7: note: candidate: A<double>::A(A<double>&&) 
    test.cpp:10:7: note: candidate expects 1 argument, 2 provided 

मैं डिफ़ॉल्ट टेम्पलेट पैरामीटर का उपयोग करने क्योंकि निर्माताओं के लिए अधिक उपयुक्त है का फैसला किया। ऑपरेटर typeid() का उपयोग इसलिए है क्योंकि मुझे कोड को मैप करते समय पढ़ने में वाकई आसान लगता है, लेकिन मैं इसे किसी भी तरह से काम नहीं कर सकता।

अन्य समाधान बहुत अजीब लगते हैं और वास्तव में अस्पष्ट हैं (जैसे इनपुट इटरेटर पैरामीटर को कुछ विधियों जैसे * इसे या ++ के लिए मजबूर करना)। यदि कोई रास्ता नहीं है तो मैं ऐसा कर सकता हूं, मैं एक कम या ज्यादा, आसानी से पढ़ा जाने वाला समाधान की सराहना करता हूं।

उत्तर

3

आदेश SFINAE करने के लिए आपको विश्वास दिलाता हूँ की जरूरत में अभिव्यक्तियों को शामिल करने का मूल्यांकन संकलन समय पर होता है।typeid के लिए निम्न लागू होगा:

जब बहुरूपी प्रकार की अभिव्यक्ति के लिए आवेदन किया, एक typeid अभिव्यक्ति के मूल्यांकन क्रम भूमि के ऊपर (एक आभासी मेज देखने), अन्यथा typeid अभिव्यक्ति संकलन समय पर हल हो गई है शामिल हो सकता है।

इस प्रकार, मैं typeid पर स्थिर (संकलन समय) बहुरूपता के लिए एक अच्छा विकल्प नहीं मानता।

एक तरह से आप अपनी समस्या को हल कर सकता है, एक सौंपने costructor के साथ संयोजन में भेजने टैग का उपयोग करके इस प्रकार है:

template <typename T> 
class A{ 
    std::vector<T> v; 

    template <typename InputIterator> 
    A(InputIterator first, InputIterator last, std::input_iterator_tag) : v(first, last) {} 

public: 

    template<typename InputIterator> A(InputIterator first, InputIterator last) 
    : A(first, last, typename std::iterator_traits<InputIterator>::iterator_category()) {} 
}; 

Live Demo

+0

मैंने कभी इस विचार के बारे में सोचा नहीं है, जो समझने और कार्यान्वित करने में वास्तव में आसान है। आपका बहुत बहुत धन्यवाद! –

1

ऑपरेटर typeid() का उपयोग इसलिए है क्योंकि मुझे कोड को मैप करते समय पढ़ने में वाकई आसान लगता है, लेकिन मैं इसे किसी भी तरह से काम नहीं कर सकता।

typeid मुख्य रूप से क्रम पर प्रकार की जानकारी खोज करते हैं एक सुविधा है। जबकि आपको इसे और अधिक "पठनीय" मिल सकता है, यह नौकरी के लिए सही उपकरण नहीं है और यह हर दूसरे सी ++ डेवलपर को भ्रमित कर देगा।


अन्य समाधान बहुत अजीब लग रही है और (InputIterator पैरामीटर के लिए मजबूर कर इस तरह के *it या ++it के रूप में कुछ तरीकों के लिए की तरह) वास्तव में पूरी तरह स्पष्ट नहीं

मैं दृढ़ता से इस पर पुनर्विचार करने की सलाह। एक InputIterator is a concept जो एक प्रकार पर वैध संचालन का वर्णन करता है। एक अवधारणा के पीछे पूरा विचार ऑपरेशन वैधता की जांच कर रहा है - its requirements से InputIterator से अधिक कुछ भी नहीं है।

सुलझाने आपकी समस्या का एक constexpr bool is_input_iterator<T> चर/समारोह है कि trueT अगर मैचों InputIterator की आवश्यकताओं रिटर्न पैदा कर रही है के सही और मुहावरेदार रास्ता। आप detection idiom का उपयोग करके आसानी से कार्यान्वित कर सकते हैं ... और यह std::enable_if_t<is_input_iterator<T>> से अधिक पठनीय नहीं है।

यहाँ

एक सरल उदाहरण (मैं सभी आवश्यकताओं के लिए जाँच नहीं कर रहा हूँ):

template <typename T> 
using supports_increment = decltype(++std::declval<T>()); 

template <typename T> 
using supports_dereference = decltype(*std::declval<T>()); 

template <typename T> 
constexpr bool is_input_iterator = 
    std::experimental::is_detected_v<supports_increment, T> 
&& std::experimental::is_detected_v<supports_dereference, T>; 

template <typename InputIterator, 
      typename = std::enable_if_t<is_input_iterator<InputIterator>>> 
    A(InputIterator first, InputIterator last) : v(first, last) {} 

live example on wandbox

+0

भले ही यह एक बहुत सुरुचिपूर्ण समाधान लग रहा है और करने के विचार को व्यक्त इनपुट इटरेटर की अवधारणा, मैं अभी भी 'decltype' से जुड़े सभी सामानों के साथ संघर्ष करता हूं। इसके अलावा, मैंने कभी भी ** पहचान idiom ** के बारे में नहीं सुना है, जो ऐसा लगता है कि यह अभी तक मानक में नहीं है (अगर मैं गलत हूं तो मुझे सही करें), और मैं वास्तव में समझ नहीं पा रहा हूं कि यह कैसे काम करता है। –

+0

मुफ्त में ऑनलाइन कई संसाधन उपलब्ध हैं जो बताते हैं कि 'decltype' और पहचान मुहावरे कैसे काम करते हैं। आप यहां प्रारंभ कर सकते हैं: https://www.youtube.com/watch?v=o1ekBpEFcPc –

+0

बहुत बहुत धन्यवाद! मैं जितनी संभव हो सके सभी declpepe दुनिया में प्रवेश करने की कोशिश करेंगे। –

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

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