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 vector
s - 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 tofind
instringValue
and then thevector
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 tofind
, and return the referencedvector
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);