c++ - লুপ কাজ না করার জন্য ভিত্তিক নির্দোষ পরিসর




for-loop c++17 (4)

নিম্নলিখিতগুলি সংকলন করে না :

#include <iostream>

int main()
{
    int a{},b{},c{},d{};

    for (auto& s : {a, b, c, d}) {
        s = 1;
    }
    std::cout << a << std::endl;
    return 0;
}

গডবোল্ট এ চেষ্টা করুন

সংকলক ত্রুটিটি: error: assignment of read-only reference 's'

এখন আমার আসল ক্ষেত্রে তালিকাটি একটি শ্রেণীর সদস্য ভেরিয়েবল দ্বারা তৈরি।

এখন, এটি কাজ করে না কারণ অভিব্যক্তিটি একটি initializer_list<int> হয়ে যায় যা আসলে একটি, বি, সি, এবং ডি অনুলিপি করে - তাই পরিবর্তনের অনুমতি দেয় না।

আমার প্রশ্ন দ্বিগুণ:

এইভাবে লুপের জন্য একটি পরিসীমা-ভিত্তিক লিখতে না দেওয়ার পিছনে কি কোনও প্রেরণা রয়েছে? যেমন। নগ্ন ধনুর্বন্ধনী এক্সপ্রেশন জন্য একটি বিশেষ ক্ষেত্রে হতে পারে।

এই ধরণের লুপটি ঠিক করার সিনট্যাক্টিক্যাল ঝরঝরে উপায় কী?

এই লাইন বরাবর কিছু পছন্দ করা হবে:

for (auto& s : something(a, b, c, d)) {
    s = 1;
}

আমি পয়েন্টার ইন্ডিয়ারেশনকে একটি ভাল সমাধান হিসাবে বিবেচনা করি না (এটি হ'ল। {&a, &b, &c, &d} the) - পুনরুক্তি ডি-রেফারেন্সযুক্ত হলে কোনও সমাধান সরাসরি উপাদান রেফারেন্স দেয়


সমাধান: একটি রেফারেন্স র‌্যাপার ব্যবহার করুন

template <class It>
struct range_view_iterator : public It{//TODO: don't inherit It
    auto& operator*() {
        return (*this)->get();
    }
};

template<class It>
range_view_iterator(It) -> range_view_iterator<It>;


template<class T>
struct range_view {
    std::vector<std::reference_wrapper<T> > refs_;
    range_view(std::initializer_list<std::reference_wrapper<T> > refs) : refs_{refs} {
    }

    auto begin() {
        return range_view_iterator{ refs_.begin() };
    }

    auto end() {
        return range_view_iterator{ refs_.end() };
    }
};

তারপর হিসাবে ব্যবহৃত:

for (auto& e : range_view<int>{a, b, c, d}) {
    e = 1;
}

এটি যদিও প্রথম প্রশ্নের উত্তর দেওয়ার চেষ্টা করে না।


আপনি স্টোর রেফারেন্সের জন্য মোড়কের ক্লাস তৈরি করতে পারেন এবং এতে এই মানটি আপডেট করার জন্য অ্যাসাইনমেন্ট অপারেটর থাকবে:

template<class T>
struct Wrapper {
    T& ref;

    Wrapper(T& ref)
    : ref(ref){}

    template<class U>
    void operator=(U u) {
        ref = u;
    }
};

template<class...T>
auto sth(T&...t) {
    return std::array< Wrapper<std::common_type_t<T...> > ,sizeof...(t) >{Wrapper(t)...};
};

int main(){
    int a{},b{},c{},d{};

    for (auto s : sth(a,b,c,d)) {
        s = 1;
    }
    std::cout << a << std::endl; // 1

সরাসরি নমুনা


ব্যাপ্তিগুলি মানুষের পছন্দ মতো যাদু নয়। শেষ অবধি, এমন একটি অবজেক্ট থাকতে হবে যা সংকলক সদস্য ফাংশন বা ফ্রি ফাংশন begin() এবং end() কল উত্পন্ন করতে পারে।

সবচেয়ে সম্ভবত আপনি সম্ভবত আসতে সক্ষম হবেন:

#include <iostream>

int main()
{
    int a{},b{},c{},d{};

    for (auto s : {&a, &b, &c, &d} ) {
        *s = 1;
    }
    std::cout << a << "\n";
    return 0;
}

যে সিনট্যাক্স সন্তুষ্ট

for (auto& s : something{a, b, c, d}) {
    s = 1;
}

আপনি মোড়ক তৈরি করতে পারেন:

template <typename T>
struct MyRefWrapper
{
public:
    MyRefWrapper(T& p)  : p(&p) {}

    T& operator =(const T& value) const { return *p = value; }

    operator T& () const { return *p; }
private:
    T* p;     
};

Demo







initializer-list