This question already has an answer here:
how to traverse a boost::multi_array
(1 answer)
Closed 8 years ago.
After searching for a while I did not find an answer to my question, so apologies in advance if this was already answered somewhere else.
I'm looking for a multi-dimensional data-structure in C++ that allows access not only as N-dimensional array, but also as 1-dimensional.
For an example assume a simple 2-dimensional matrix (it could go to higher dimensions, but in that case let's stick to this example). In most cases the member will be accessed in row-colum-form, e.g. matrix[x][y]. In other cases it might be desireable to access all members as a single list, e.g. for matrix addition using std-algorithms.
Standard-Approach would probably be something like std::array<std::array<double, 4>, 4> and write additionally an iterator with linear access to all members and maybe an extra accessor function.
A second approach is the other way around std::array<double, 16> with accessors in row-colum-form, but in this case it gets tricky to return whole columns .
Or maybe it is doable with boost MultiArray, but I think reducing the dimensions of a MultiArray always results in only getting slices of the MultiArray.
My question boils down to: Is there already an implementation in the standard-library or some well-known library, like boost, for this? If not, am I missing a point and there is a simpler method than the ones I wrote about?
EDIT: I was not looking for only iteration over all values, like in the mentioned question. But however from the pointed documentation I could find that MultiArray can be accessed as C-style array which is enough for my needs. This can then be closed and thanks for all answers
See boost::multi_array::data() and boost::multi_array::num_elements().
As with std::vector, it would appear you can just access it as a solid block of memory by index, if that's all you want. I've never done this, but looks like you can. Just because you can doesn't necessarily mean you should, but, well...
See this answer:
how to traverse a boost::multi_array
There is something like what you are looking for: std::valarray<T>. Well, the intend of the std::valarray<T> class template is to provide different views on the same array and to support potentially vectorized evaluation. That said, it doesn't really work and probably few people are using it.
However, from what you described you probably want to have something providing an array view on an existing array. I'd be pretty sure that this was implemented before, if nothing else as a replacement for std::valarray<T> but I can't point to an implementation.
Related
I most often work with python and therefore I'm used to being able to put a bool and integer in a single list. I realize that C++ has a different paradigm, however, I imagine that there is a workaround to this issue. Ideally I want a vector that could contain data that looks like {1, 7, true, 8, false, true, 9}. So this vector would have to be defined with syntax like (vector int bool intBoolsVec), however, I realize that isn't proper syntax.
I see that some people suggest using variant that was introduced in C++17, is this the best solution? Seems like this would be a common problem if C++ doesn't easily allow you to work with heterogenous containers, even if those containers are constrained to a couple defined types like a vector that only takes only ints and bools.
What is the easiest way to create a vector that contains both integers and booleans in C++? If someone could also provide me more insight on why C++ doesn't have an easy/obvious way to do this, that might help me better understand C++ as well.
My approach would probably be to create my own class, which does exactly what I want it to do. This might be your easiest solution, besides using std::any. Also, you could combine those by creating a custom array of std::any which only allows integers and booleans at certain entries for your example. This would be similar, but not equal to an array of std::variant. Also, In C++ you can store 2 types in a std::pair, if that fits your use-case.
As a simple example, take a look at this code (or imagine array-specific code rather than templates and other general coding techniques):
int a[] = {1,2,3,7,8,9,55};
vector<int> v(a, end(a));
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
I was wondering if there is a coding reason to use std::begin here or in perhaps different settings (other than style/consistency/compatibility with future code changes/etc.). Would there be a place where it is actually required?
What are your thoughts on using begin(a) there in terms of coding practices? To me, it's a touchy topic, because you risk the appearance of not knowing about the fundamental operation of arrays and pointers in C++ if you mindlessly call std::begin. Realistically, I may never need the ability to change containers. I mean, come on. If you actually changed the container, you'd get a compiler bug and fix it in 3 seconds.
You've heard of "premature optimization". I'd call using std::begin here "premature generality".
As a practice, using begin in this context really doesn't hold any of the downsides you think it holds. On the contrary, not using it seems inconsistent and a pointless complication for the sake of showing off that you understand an aspect of how C++ works. It will cause the next guy to look at this code to look twice to understand why you didn't use begin and end symmetrically, wasting time.
More concretely, using begin here allows you to change out the type of a without breaking any code.
What are your thoughts on using begin(a) there in terms of coding
practices?
Use it.
Assuming you're talking about using begin as opposed to indexing an array (eg arry[0]), your presumption that changing a container and fixing the resulting compiler errors will be simple is unrealistic.
Imagine a codebase consisting of 1,000,000 lines of code in dozens of different modules spread out all over the place. You might be trying to access this collection from anywhere, and from places you have long since forgotten about. It could take hours or days to fix all the compiler errors. The example is not contrived. The codebase I work on is several million lines of code -- some of which I forgot about years ago.
You should only use it when writing templates.
In regular code you're right, it's not needed.
If you write templates that work with containers then you don't know if it's a regular array or vector or something else. So using x.begin() will not work for arrays and any thing that works with arrays will not work with STL containers. So you use begin to bridge the gap and ignore the differences so that the template just works with both arrays and STL containers.
I have a quick question for you all. I'm trying to convert over some ActionScript code to C++ and am having a difficult time with this one line:
private var edges:Vector.<Array>
What is this exactly? Is this essentially a multidimensional vector then? Or is this simply declaring the vector as a container? I understand from researching that vectors, like C++ vectors, have to be declared with a type. However, in C++ I can't just put down Array, I have to use another vector (probably) so it looks like:
vector<vector<T> example;
or possibly even
vector<int[]> example;
I don't expect you guys to know the C++ equivalent because I'm primarily posting this with AS tags, but if you could confirm my understand of the AS half, that would be great. I did some googling but didn't find any cases where someone used Array as it's type.
From Mike Chambers (adobe evangelist) :
"Essentially, the Vector class is a typed Array, and in addition to ensuring your collection is type safe, can also provide (sometimes significant) performance improvements over using an Array."
http://www.mikechambers.com/blog/2008/08/19/using-vectors-in-actionscript-3-and-flash-player-10/
Essentially the vector in C++ is based on the same principles. As far as porting a vector of Arrays in AS3 to C++, well that's not a conversion that is clear cut in principle, as you could have a collection (array) of various types in C++, such as a char array. However, it appears you've got the idea, as you've pretty much posted examples of both avenues in your question.
I would post some code but I think you've got it exactly. Weather you use a vector within a vector or you declare a specifically typed collection I think comes down to a matter of what works best for you specific project.
Also you might be interested in:
http://www.mikechambers.com/blog/2008/09/24/actioscript-3-vector-array-performance-comparison/
i want to store some kind of distance-matrix (2D), where each entry has some alternatives (different coordinates). So i want to access the distance for example x=1 with x_alt=3 and y=3 with y_alt=1, looking in a 4-dim multi-array with array[1][3][3][1].
The important thing to notice is the following: the 2 most inner arrays/vectors don't have the same size for different values of the outer ones.
After a first init step, where i calculate the values, no more modifying is needed!
This should be easily possible with the use of stl-vectors:
vector<vector<vector<vector<double> > > >`extended_distance_matrix;
where i can dynamically iterate over the outer 2 dimensions and fill only as much alternatives to the inner 2 dimensions as i need (e.g. with push_back()).
Questions:
Is this kind of data-structure definition possible with Boost.MultiArray? How?
Is it a good idea to use Boost.MultiArray instead of the nested vectors? Performance (especially lookups! (Memory-layout))? Easy of use?
Thanks for any input!
sascha
PS: The boost documentation didn't help me. Maybe one can use multi_array_ref to get already sized arrays into the whole 4D-structure?
Edit:
At the moment i'm thinking of another approach: flattening the alternatives -> one bigger matrix with all the distances between the alternatives. Then i only need to calc the number of alternatives per node, build up the prefix sum (which is describing the matrix position/shift) and can then access the information in a 2-step-way.
But my questions are still open.
it sounds like you need:
multi_array<ublas::matrix<type>,2>
Boost.MultiArray deals with contiguous memory (arranged logically in many dimensions) so it is difficult to add elements in the inner dimensions. MultiArrays can be dynamically resized, e.g. to add elements in any dimension, but this is a costly operation that almost certainly need (internally) reallocation and copying.
Because of that requirement MultiArray is not the best option. But from what you say it looks like a combination of the two would be appropriate to you.
boost::multi_array<std::vector<std::vector<type>>, 2> data
The very nice thing is that the indexing interface doesn't change with respect to boost::multi_array<type, 4>. For example data[1][2][3][4] still makes sense.
I don't know from your post how you handle the inner dimension but it could even make sense to use this:
boost::multi_array<boost::multi_array<type>, 2>, 2> data
In any case, unless you really need to do linear algebra I would stay away from boost::ublas::array, or at most use it for the internal array if type is numeric. boost::multi_array<boost::ublas::array<type>, 2> data which is mentioned in the other answer.
I was browsing the SGI STL documentation and ran into project1st<Arg1, Arg2>. I understand its definition, but I am having a hard time imagining a practical usage.
Have you ever used project1st or can you imagine a scenario?
A variant of project1st (taking a std::pair, and returning .first) is quite useful. You can use it in combination with std::transform to copy the keys from a std::map<K,V> to a std::vector<K>. Similarly, a variant of project2nd can be used to copy the values from a map to a vector<V>.
As it happens, none of the standard algorithms really benefits from project1st. The closest is partial_sum(project1st), which would set all output elements to the first input element. It mainly exists because the STL is heavily founded in mathematical set theory, and there operations like project1st are basic building blocks.
My guess is that if you were using the strategy pattern and had a situation where you needed to pass an identity object, this would be a good choice. For example, there might be a case where an algorithm takes several such objects, and perhaps it is possible that you want one of them to do nothing under some situation.
Parallel programming. Imagine a situation where two processes come up with two valid but different results for a given computation, and you need to force them to be the same. project1st/2nd provides a very convenient way to perform this operation on a whole container, using an appropriate parallel call that takes a functor as an argument.
I assume that someone had a practical use for it, or it wouldn't have been written, but I'm drawing a blank on what it might have been. Presumably its use-case is similar to the identity function that the description mentions, where there's no real need for processing but the syntax requires a functor anyway.
The example on that same page suggests using it with the two-container form of std::transform, but if I'm not mistaken, the way they're using it is functionally identical to std::copy, so I don't see the point.
It looks like a solution in search of a problem to me.