4

I'm not really versed in C++, but I came to the following code:

BaseManager* allManagers[] = { mColorManager, mToolManager, mLayerManager, mPlaybackManager, mViewManager }; for ( BaseManager* pManager : allManagers ) { pManager->setEditor( this ); pManager->init(); } 

I use an older g++, so I cannot use -std=c++11, and I have to use -std=c++0x. Looking at the "old-school" equivalent in error: expected initializer before ‘:’ token, I would have hoped the following would work:

for ( auto it = allManagers.begin(); it != allManagers.end(); ++it ) { BaseManager* pManager = *it; pManager->setEditor( this ); pManager->init(); } 

... but it fails with:

error: request for member ‘begin’ in ‘allManagers’, which is of non-class type ‘BaseManager* [5]’ error: unable to deduce ‘auto’ from ‘<expression error>’ 

So I gathered, since this allManagers is apparently just a C array, it is not an object with methods (like .begin) - so in the end, I finally got that piece to compile with:

for ( int i=0 ; i<5 ; i++ ) { BaseManager* pManager = allManagers[i]; pManager->setEditor( this ); pManager->init(); } 

... however, that requires me to write in the array length manually, which I don't like.

So, my question is: what would be the proper way to iterate through such an array of pointers without using a range-based for loop - but also, without having to explicitly enter the hardcoded array length?

1
  • The iterator versions below are better, but: for ( int i = 0; i < (sizeof(allManagers) / sizeof(allManagers[0])); ++i ) is a C-ish way to do it. Commented Jan 8, 2015 at 23:25

3 Answers 3

6

You can use:

for ( auto it = std::begin(allManagers); it != std::end(allManagers); ++it ) { 

However, these are also C++11 features. Some pre C++11 compilers might support them but it is not guaranteed.

Without a C++11 compiler to work with, you can use:

size_t numObjects = sizeof(allManagers)/sizeof(allManagers[0]); for ( size_t i = 0; i < numObjects; ++i ) { BaseManager* manager = allManagers[i]; 
Sign up to request clarification or add additional context in comments.

4 Comments

Nice, totally didn't realize that was in the standard library. For OP, too, look here for how to implement them if you're curious: stackoverflow.com/questions/5897319/…
Thanks @RSahu - I was really looking forward to this, but apparently I have a compiler which is too old, as I got "error: ‘begin’ is not a member of ‘std’" ...
As of C++ 17, sizeof(allManagers)/sizeof(allManagers[0]) can be std::size(allManagers). This has the advantage of not compiling, rather than being fooled and providing the correct answer only by dumb luck, if the array has decayed to a pointer.
@user4581301, if using C++17, there is no need use sizeof or std::size. The suggested solution for C++11 should be the preferred method.
2

Either track the array length in a variable or use an std::array or std::vector.

Edit: If you want to create your own ArrayLen() method, you can do this:

template<class T, size_t Size> static inline size_t ArrayLen(const T(&arr)[Size]) { return Size; } 

Then you can do this:

for(size_t i = 0; i < ArrayLen(allManagers); ++i) { BaseManager * pManager = allManagers[i]; 

2 Comments

Thanks @mbgda - does that mean, that there is no function in "old" c++ to determine the length of a "plain" C array (as in, pseudocode, int mylen = len(allManagers);)?
@sdaau You can get the length of the array using modified code from the page I linked elsewhere, like this: template<class T, size_t Size> size_t ArraySize(const T(&array)[Size]) { return Size; }
1

allManagers is not a container. It is an array of pointers, thus you can not use .begin().

If you want to determine the size of your array, just do this:

int n = sizeof(allManagers)/sizeof(allManagers[0]); 

Check this question for more. Notice that your array is in the stack.

4 Comments

Thanks for confirming that, @G.Samaras
You are welcome @sdaau. Take a look at my edit. Nice question by the way.
Thanks again, @G.Samaras - the edit was exactly what I needed; I tried the counted for loop for ( int i=0 ; i< (sizeof allManagers / sizeof allManagers[0]) ; i++ ) and it compiled just fine! So I'm accepting this answer (even if I wish I could have used the syntax noted by @RSahu). Cheers!
You are welcome. The compiler will probably do this for you (with the needed optimization flag), but you it would be nice to "cache" the result of a division to a variable (just like in my answer) and put that in the control of for. Otherwise, it will be executed every time you perform the for check! @sdaau

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.