Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterating through array of object pointers in C++ the old way (without range-based for)?

Tags:

c++

arrays

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?

like image 794
sdaau Avatar asked Sep 15 '25 21:09

sdaau


2 Answers

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];
like image 54
R Sahu Avatar answered Sep 18 '25 19:09

R Sahu


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];
like image 42
mbgda Avatar answered Sep 18 '25 18:09

mbgda