मुझे अक्सर ऐसी स्थितियों का सामना करना पड़ता है जहां मुझे डेटा स्रोत से चयन बनाने की आवश्यकता होती है, चयन में हेरफेर करें और मूल डेटा स्रोत में परिवर्तन वापस खिलाएं। कुछ इस तरह

#include <vector>

void manipulate(std::vector<int> &vector) {
    // Manipulate vector...
}

int main() {
    // Data source
    std::vector<int> dataSource{1, 2, 3, 4};

    // Select every second entry
    std::vector<int> selection{v[0], v[2]};

    // Manipulate selection
    manipulate(selection);

    // Feed data back to the data source
    dataSource[0] = selection[0];
    dataSource[2] = selection[1];

    return 0;
}

डेटा स्रोत में डेटा वापस भेजने की प्रक्रिया को स्वचालित करने के लिए, मैं चयन को वेक्टर या बिंदुओं या संदर्भों (std::reference_wrapper का उपयोग करके) में बदल सकता हूं और उस फ़ंक्शन को पास कर सकता हूं जो इसके तर्क में हेरफेर करता है। वैकल्पिक रूप से, मैं एक वर्ग ObservableVector बना सकता हूं जो डेटा स्रोत को एक सदस्य के रूप में रखता है और डेटा स्रोत में किए गए सभी परिवर्तनों का प्रचार करता है। हालाँकि, दोनों मामलों में, मुझे संकेत के वेक्टर या ObservableVector को स्वीकार करने के लिए manipulate के हस्ताक्षर को बदलने की आवश्यकता होगी। क्या कोई मौका है जो मैं मूल manipulate फ़ंक्शन (बिना आवरण फ़ंक्शन बनाने की आवश्यकता के बिना) रख सकता हूं और फिर भी डेटा को मूल स्रोत पर वापस भेजने की प्रक्रिया को स्वचालित कर सकता हूं?

0
Marcel 30 नवम्बर 2015, 11:23

2 जवाब

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

आप अपने तर्क को किसी फ़ंक्शन में लपेट सकते हैं, जैसे कुछ:

template <typename T, typename F>
void manipulate_selection(std::vector<T>& v,
                          F f,
                          const std::vector<std::size_t>& indexes)
{
    std::vector<T> selection;

    // Select every second entry
    selection.reserve(indexes.size());
    for (auto index : indexes) {
        selection.pusk_back(v[index]);
    }

    // Manipulate selection
    f(selection);

    // Feed data back to the data source
    for (std::size_t i = 0; i != indexes.size(); ++i) {
        v[indexes[i]] = selection[i];
    }
}

और फिर इसका उपयोग करें जैसे:

manipulate_selection(dataSource, manipulate, {0, 2});
0
Jarod42 30 नवम्बर 2015, 08:43

एक range पुस्तकालय पर एक नज़र डालें, उदा। Boost.Range। एक कंटेनर से एक श्रेणी बनाई जा सकती है जिसमें कंटेनर का सबसेट होता है, उदा। प्रत्येक nth तत्व, या सभी तत्वों के साथ एक श्रेणी जो एक विधेय वस्तु से मेल खाती है। इसके साथ, जटिल जोड़तोड़ की रचना करना आसान है। निम्नलिखित कुछ नमूना कोड है जो कंटेनर के हर दूसरे तत्व से अधिक है, इसे फ़िल्टर करता है और फिर कुछ गणना करता है

using namespace boost::adaptors;
using namespace boost;

// assume we have a predicate int -> bool
bool pred(int x);

// some function which transforms each element
int computation(int);

std::vector<int> elements = // ...

auto everySecondElement = elements | strided(2);
auto filtered = everySecondElement | filtered(pred);

transform( filtered, filtered.begin(), computation);

यह एक फ़ंक्शन-प्रोग्रामिंग शैली है जो रेंज प्रोसेसिंग की संरचना को वास्तव में आसान और अभिव्यंजक बनाती है। इसे संभवतः आपके हेरफेर कार्यों में बदलाव की आवश्यकता है, लेकिन मुझे लगता है कि एक सीमा पुस्तकालय का उपयोग करके सी ++ कोड में बहुत सुधार होता है।

2
Jens 30 नवम्बर 2015, 08:52