मेरे पास एक Container वर्ग है जो साझा पॉइंटर्स के वेक्टर को स्टोर करने के लिए है। जब भी कोई आइटम Container में जोड़ा जाता है, तो मैं चाहता हूं कि वह उस आइटम का स्वामित्व ग्रहण करे। दूसरे शब्दों में, जब Container का पुनर्निर्माण किया जाता है, तो उसके अंदर के सभी तत्वों को भी विघटित किया जाना चाहिए।

template <typename T>
class Container
{
private:
    const std::vector<std::shared_ptr<T>> vec_;


public:
    void append(std::shared_ptr<T> item)
    {
        vec_.push_back(std::move(item));
    }

    void printElements()
    {
        for (int i = 0; i < vec_.size(); i++) { std::cout << vec_[i] << std::endl; }
    }
};

int main(int argc, char** argv) {

    std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();
    c->append(std::make_shared<std::string>("hello"));

    return 0;
}

समस्या यह है कि, मुझे vec_.push_back(std::move(item)) पर निम्न त्रुटि मिलती है।

No matching member function for call to 'push_back'

मुझे यकीन नहीं है कि यह त्रुटि क्यों हो रही है।

1
Carpetfizz 10 मई 2020, 07:33

1 उत्तर

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

मूल उत्तर:

आपका std::vector, vec_ const है। मुझे लगता है कि push_back() जैसी किसी भी विधि को जबरदस्ती हटा या अक्षम कर देगा, जो कॉन्स्ट वेक्टर को संशोधित करने का प्रयास करता है।


अतिरिक्त जोड़े गए 10 मई 2020:

मुझे लगता है कि इस टिप्पणी पर @Carpetfizz से उनके प्रश्न के तहत टिप्पणियों में भी विस्तार करना उचित है:

@GabrielStaples धन्यवाद, const को हटाकर चाल चली। मैंने सोचा था कि const केवल वेक्टर_ के पुन: असाइनमेंट के खिलाफ सुरक्षित है लेकिन इसे उत्परिवर्तित करने की अनुमति है?

मेरी प्रतिक्रिया:

नहीं, const यहां वेक्टर की सामग्री पर लागू होता है। सदिश एक सूचक नहीं है, लेकिन आप जिसके बारे में बात कर रहे हैं, वह सूचक के साथ किया जा सकता है, सूचक को const की सामग्री के बजाय जो इसे इंगित करता है const। साथ ही, const और mutable विपरीत हैं। एक दूसरे को पूर्ववत करता है। आप दोनों एक ही समय में प्रभावी नहीं हो सकते। परिभाषा के अनुसार, कुछ स्थिर अपरिवर्तनीय (अपरिवर्तनीय) है, और कुछ परिवर्तनीय गैर-स्थिर है।

और कोई कैसे एक पॉइंटर कास्ट बना सकता है, लेकिन इसकी सामग्री को नहीं जो यह इंगित करता है?

सबसे पहले, मूल कोड पर विचार करें (कुछ मामूली संशोधनों/सुधारों के साथ मैंने इसे किया था):

इसे स्वयं यहां ऑनलाइन चलाएं: https://onlinegdb.com/SyMqoeU9L

1) cpp_template_const_vector_of_smart_ptrs_test_BEFORE.cpp:

#include <iostream>
#include <memory>
#include <vector>

template <typename T>
class Container
{
private:
    // const std::vector<std::shared_ptr<T>> vec_; // does NOT work 
    std::vector<std::shared_ptr<T>> vec_;          // works!


public:
    void append(std::shared_ptr<T> item)
    {
        vec_.push_back(std::move(item));
    }

    void printElements()
    {
        for (int i = 0; i < vec_.size(); i++) 
        { 
            // Don't forget to dereference the pointer with `*` in order to 
            // obtain the _contens of the pointer_ (ie: what it points to),
            // rather than the pointer (address) itself
            std::cout << *vec_[i] << std::endl; 
        }
    }
};

int main(int argc, char** argv) 
{
    std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();

    c->append(std::make_shared<std::string>("hello"));
    c->append(std::make_shared<std::string>("world"));

    c->printElements();

    return 0;
}

आउटपुट:

hello
world

और यहां नया कोड प्रदर्शित करता है कि गैर-कॉन्स्ट वेक्टर को निरंतर सूचक कैसे बनाया जाए। मेरी टिप्पणियाँ यहाँ देखें, और परिवर्तनों का अध्ययन करें:

इसे स्वयं यहां ऑनलाइन चलाएं: https://onlinegdb.com/HyjNx-L5U

2) cpp_template_const_vector_of_smart_ptrs_test_AFTER.cpp

#include <iostream>
#include <memory>
#include <vector>

template <typename T>
class Container
{
private:
    // const std::vector<std::shared_ptr<T>> vec_; // does NOT work 

    // Create an alias to this type just to make the creation below less 
    // redundant in typing out the long type 
    using vec_type = std::vector<std::shared_ptr<T>>;

    // NON-const object (vector)--so it can be changed 
    vec_type vec_;
    // const pointer to NON-const object--so, vec_p_ can NOT be re-assigned to
    // point to a new vector, because it is `const`! But, **what it points to**
    // CAN be changed because it is NOT const!
    vec_type * const vec_p_ = &vec_;

    // This also does NOT work (in place of the line above) because it makes 
    // the **contents of what you're pointing to const**, which means again 
    // that the contents of the vector can NOT be modified. 
    // const vec_type * const vec_p_ = &vec_; // does NOT work 
    // Here's the compile-time error in gcc when compiling for C++17:
    //      main.cpp: In instantiation of ‘void Container<T>::append(std::shared_ptr<_Tp>) [with T = std::basic_string<char>]’:
    //      <span class="error_line" onclick="ide.gotoLine('main.cpp',78)">main.cpp:78:53</span>:   required from here
    //      main.cpp:61:9: error: passing ‘const vec_type {aka const std::vector >, std::allocator > > >}’ as ‘this’ argument discards qualifiers [-fpermissive]
    //               vec_p_->push_back(std::move(item));
    //               ^~~~~~
    //      In file included from /usr/include/c++/7/vector:64:0,
    //                       from main.cpp:22:
    //      /usr/include/c++/7/bits/stl_vector.h:953:7: note:   in call to ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::shared_ptr >; _Alloc = std::allocator > >; std::vector<_Tp, _Alloc>::value_type = std::shared_ptr >]’
    //             push_back(value_type&& __x)
    //             ^~~~~~~~~


    // To prove that vec_p_ can NOT be re-assigned to point to a new vector, 
    // watch this:
    vec_type vec2_;
    // vec_p_ = &vec2_; // COMPILE-TIME ERROR! Here is the error:
    //      main.cpp:44:5: error: ‘vec_p_’ does not name a type; did you mean ‘vec_type’?
    //           vec_p_ = &vec2_; // COMPILE-TIME ERROR!
    //           ^~~~~~
    //           vec_type

    // BUT, this works just fine:
    vec_type * vec_p2_ = &vec2_; // non-const pointer to non-const data 

public:
    void append(std::shared_ptr<T> item)
    {
        vec_p_->push_back(std::move(item));
    }

    void printElements()
    {
        for (int i = 0; i < vec_p_->size(); i++) 
        { 
            // Notice we have to use a double de-reference here now!
            std::cout << *(*vec_p_)[i] << std::endl; 
        }
    }
};

int main(int argc, char** argv) 
{
    std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();

    c->append(std::make_shared<std::string>("hello"));
    c->append(std::make_shared<std::string>("world"));

    c->printElements();

    return 0;
}

आउटपुट:

hello
world
3
Gabriel Staples 11 मई 2020, 01:59