मैं सी ++ में एक सामान्य लिंक्ड सूची और लिंक्ड सूची इटरेटर को लागू करने की कोशिश कर रहा हूं। मेरे पास एक नोड संरचना इस प्रकार है

template <typename T>
struct Node
{
    T m_data;
    Node<T>* m_next;
};

मेरे पास एक लिंक्ड सूची इटरेटर भी है जो एक टेम्पलेट है इसलिए यह नियमित और const इटरेटर दोनों उत्पन्न कर सकता है।

template <typename NodeType>
class LinkedListIterator
{  
private:
    NodeType* m_node;
public:
    LinkedListIterator(NodeType* n);
    T& operator*() const;
};

मेरा प्रश्न यह है कि मैं operator*() फ़ंक्शन को ठीक से कैसे घोषित करूं? मेरी अपेक्षा यह है कि निम्नलिखित की तरह कुछ काम करना चाहिए:

LinkedListIterator<const Node<T>> my_iter(some_node_pointer);
*my_iter = new_value; // should not work

मैं समझता हूं कि T को operator*() में वापस करने का कोई मतलब नहीं है क्योंकि इस वर्ग के पास Node वर्ग में टाइपनाम तक पहुंच नहीं है।

मुझे Node वर्ग के अंदर प्रकार के लिए उपनाम बनाकर एक काम मिला, जैसे so

template <typename T>
struct Node
{
    typedef T type_value;
    // rest of Node class...
};

और अब मैं अपने इटरेटर वर्ग में निम्नलिखित कर सकता हूं:

template <typename NodeType>
class LinkedListIterator
{
public:
    typename NodeType::type_value& operator*() const;
};

ऐसा लगता है कि यह काम करता है और सही मूल्य लौटाएगा। तो मेरा सवाल वास्तव में होना चाहिए, क्या इसे लागू करने का यह सबसे अच्छा तरीका है? क्या मुझे एक उपनाम बनाने के लिए typedef की आवश्यकता है ताकि मैं उस प्रकार का उपयोग कर सकूं? या LinkedListIterator वर्ग के अंदर के प्रकार को निर्धारित करने का कोई तरीका है?

1
nick2225 14 अगस्त 2020, 23:36

1 उत्तर

सबसे बढ़िया उत्तर

इस तरह typedef का उपयोग करना इसे करने का प्रामाणिक तरीका है और अक्सर मानक पुस्तकालय में किया जाता है। वास्तव में, सभी LegacyIteratorsको value_type, difference_type, reference, pointer, और iterator_category. तभी उनके लक्षणों को std::iterator_traits का उपयोग करके सार्वभौमिक रूप से एक्सेस किया जा सकता है.

उदाहरण के लिए:

// a simple forward iterator
struct Iterator {
    using value_type = int;
    using reference = value_type &;
    using pointer = value_type *;
    using difference_type = std::ptrdiff_t;
    using iterator_category = std::forward_iterator_tag;

    // LegacyIterators also need two operators to be defined:

    // the result of operator* is unspecified, we can choose it freely
    value_type operator*();
    // operator++ needs to return a reference to self
    Iterator& operator++();
};

// we can now access the traits universally, as can various standard library functions
static_assert (std::is_same_v<std::iterator_traits<Iterator>::value_type, int> );

संक्षेप में, आप जो कर रहे हैं वह इसके बारे में जाने का सही तरीका है, लेकिन आपको इन सटीक नामों से चिपके रहना चाहिए ताकि मानक पुस्तकालय आपके पुनरावर्तक के लक्षणों तक पहुंच सके। साथ ही मैं typedef के बजाय using का उपयोग करने की सलाह दूंगा। इसमें न केवल एक दृश्य विभाजक के रूप में = है, बल्कि यह सार्वभौमिक रूप से लागू है, उदा। इसे typedef के विपरीत टेम्प्लेट किया जा सकता है। देखें C++11 में 'typedef' और 'use' के बीच क्या अंतर है?

5
Jan Schultke 15 अगस्त 2020, 01:25