Home > Net >  C : is it possible to use "universal" pointer to vector?
C : is it possible to use "universal" pointer to vector?

Time:10-27

Good day, SO community! I am new to C and I've ran into a situation in my project, where I have 2 vectors of similar paired data types:

std::vector<std::pair<int, std::string> firstDataVector
std::vector<std::pair<int, std::string> secondDataVector

and in one part of the code I need to select and process the vector depending on the external string value. So my question is - is it possible to create a pointer to vector outside of the conditions

if (stringValue.find("firstStringCondition"))
{
    //use firstDataVector
}
if (stringValue.find("secondStringCondition"))
{
    //use secondDataVector
}

some kind of pDataVector pointer, to which could be assigned the existing vectors (because now project has only two of them, but the vectors count might be increased)

I've tried to createstd::vector<std::string> &pDataVector pointer, but it will not work because reference variable must be initialized. So summarizing the question - is it possible to have universal pointer to vector?

CodePudding user response:

You are trying to create a reference to one of the vectors - and that's certainly possible, but it must be initialized to reference it. You can't defer it.

It's unclear what you want to happen if no match is found in stringValue so I've chosen to throw an exception.

now project has only two of them, but the vectors count might be increased

  • Create a vector with a mapping between strings that you would like to try to find in stringValue and then the vector you'd like to create a reference to.
  • When initializing pDataVector, you can call a functor, like a lambda, that returns the reference.
  • In the functor, loop over the vector holding the strings you'd like to try to find, and return the referenced vector on the first match you get.

It could look like this:

#include <functional>
#include <iostream>
#include <string>
#include <vector>

int main() {
    using vpstype = std::vector<std::pair<int, std::string>>;

    vpstype firstDataVector{{1, "Hello"}};
    vpstype secondDataVector{{2, "World"}};

    // A vector of the condition strings you want to check keeping the order
    // in which you want to check them.
    std::vector<std::pair<std::string, std::reference_wrapper<vpstype>>>
        conditions{
            {"firstStringCondition", firstDataVector},
            {"secondStringCondition", secondDataVector},
            // add more mappings here
        };

    // an example stringValue
    std::string stringValue = "ssdfdfsdfsecondStringConditionsdfsfsdf";

    // initialize the vpstype reference:
    auto& pDataVector = [&]() -> vpstype& {
        // loop over all the strings and referenced vpstypes:
        for (auto& [cond, vps] : conditions) {
            if (stringValue.find(cond) != std::string::npos) return vps;
        }
        throw std::runtime_error("stringValue doesn't match any condition string");
    }();

    // and use the result:
    for (auto [i, s] : pDataVector) {
        std::cout << i << ' ' << s << '\n'; // prints "2 world"
    }
}

CodePudding user response:

You can indeed inintialize references conditionally. Either use a function or lambda that returns the vector you want to reference, or hard code it like below.

std::vector<std::string> &pDataVector = 
    (stringValue.find("firstStringCondition") != std::string::npos) ?
        firstDataVector : ((stringValue.find("secondStringCondition") != std::string::npos) ?
            secondDataVector : thirdDataVector);
  • Related