Use an array, a vector (or list) or a map, depending on what is most practical.
An array is inflexible, fixed size at compile to. A std::vector<double>
is flexible and easy to use. For example:
#include <iostream>
#include <numeric> // for std::accumulate, also look at <algorithms>
#include <vector>
struct data {
std::vector<double> nodes;
};
int main() {
data d = {{1, 2, 3}};
double sum = std::accumulate(std::begin(d.nodes), std::end(d.nodes), 0);
std::cout << "Total: " << sum << std::endl;
}
Use a std::map<std::string, double>
(or std::unordered_map
) if you would prefer to use names rather than indexes.
#include <iostream>
#include <map>
#include <numeric>
#include <string>
struct data {
std::map<std::string, double> items;
};
typedef std::map<std::string, double>::value_type my_map_element;
int main() {
data d = {{{"item1", 1}, {"item2", 2}, {"item3", 42}}};
double sum = std::accumulate(std::begin(d.items), std::end(d.items), 0,
[](double partial, my_map_element const& elt) {
return partial+elt.second;
});
//[](auto partial, auto const& elt) { // C++14
// return partial+elt.second;
//});
std::cout << "Total: " << sum << std::endl;
}
std::accumulate
, like most standard algorithms, takes iterators. You'll find that all over the place in generic C++ libraries. This makes the algorithms very flexible - they don't depend on the actual data structure being used.
If you can't change the data classes, you can use simple wrappers to make them iterable (one type at a time anyway) without much trouble using std::reference_wrapper
which behaves pretty much like a reference, but can be stored in collections (and arrays).
Here's an example of how that could work:
#include <functional> // for std::reference_wrapper
#include <iostream>
#include <numeric> // for std::accumulate
#include <vector>
struct data
{
double node1, node2, node3;
};
int main()
{
typedef std::vector<std::reference_wrapper<double>> double_wrapper;
data d { 1, 2, 3 };
double_wrapper helper = { d.node1, d.node2, d.node3 };
// You update via the helper or directly
d.node1 = 4;
helper[1].get() = 5; // will update d.node2
// Handy iteration
for (auto& node: helper)
node.get()++;
// And use standard algorithms
std::cout
<< "Sum: "
<< std::accumulate(std::begin(helper), std::end(helper), 0)
<< std::endl;
}
Warning though: the lifetime of the helper/wrapper is deeply tied to the lifetime of the data object itself. Don't let the wrapper outlive the data object. If you "repackage" the external data and something like the vector above in a struct for your internal use, also be very careful about copy (and move) semantics, for the same reason.