C++ for each, pulling from vector elements

C++For LoopVectorEach

C++ Problem Overview


I am trying to do a foreach on a vector of attacks, each attack has a unique ID say, 1-3.

The class method takes the keyboard input of 1-3.

I am trying to use a foreach to run through my elements in m_attack to see if the number matches, if it does... do something.

The problem I'm seeing is this:

a'for each' statement cannot operate on an expression of type "std::vector<Attack

Am I going about this totally wrong, I have C# experience and is kind of what I'm basing this on, any help would be appreciated.

My code is as follows:

In header

vector<Attack> m_attack;

In class

int Player::useAttack (int input)
{

    for each (Attack* attack in m_attack) // Problem part
    {  
        //Psuedo for following action
     	if (attack->m_num == input)
     	{
            //For the found attack, do it's damage
    		attack->makeDamage();
     	}
    }
}

C++ Solutions


Solution 1 - C++

For next examples assumed that you use C++11. Example with ranged-based for loops:

for (auto &attack : m_attack) // access by reference to avoid copying
{  
    if (attack->m_num == input)
    {
        attack->makeDamage();
    }
}

You should use const auto &attack depending on the behavior of makeDamage().

You can use std::for_each from standard library + lambdas:

std::for_each(m_attack.begin(), m_attack.end(),
        [](Attack * attack)
        {
            if (attack->m_num == input)
            {
                attack->makeDamage();
            }
        }
);

If you are uncomfortable using std::for_each, you can loop over m_attack using iterators:

for (auto attack = m_attack.begin(); attack != m_attack.end(); ++attack)
{  
    if (attack->m_num == input)
    {
        attack->makeDamage();
    }
}

Use m_attack.cbegin() and m_attack.cend() to get const iterators.

Solution 2 - C++

This is how it would be done in a loop in C++(11):

   for (const auto& attack : m_attack)
    {  
        if (attack->m_num == input)
        {
            attack->makeDamage();
        }
    }

There is no for each in C++. Another option is to use std::for_each with a suitable functor (this could be anything that can be called with an Attack* as argument).

Solution 3 - C++

The for each syntax is supported as an extension to native c++ in Visual Studio.

The example provided in msdn

#include <vector>
#include <iostream>

using namespace std;

int main() 
{
  int total = 0;

  vector<int> v(6);
  v[0] = 10; v[1] = 20; v[2] = 30;
  v[3] = 40; v[4] = 50; v[5] = 60;

  for each(int i in v) {
    total += i;
  }
 
  cout << total << endl;
}

(works in VS2013) is not portable/cross platform but gives you an idea of how to use for each.

The standard alternatives (provided in the rest of the answers) apply everywhere. And it would be best to use those.

Solution 4 - C++

C++ does not have the for_each loop feature in its syntax. You have to use c++11 or use the template function std::for_each.

struct Function {
    int input;
    Function(int input): input(input) {}
    void operator()(Attack& attack) {
        if(attack->m_num == input) attack->makeDamage();
    }
};
Function f(input);
std::for_each(m_attack.begin(), m_attack.end(), f);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSpringfoxView Question on Stackoverflow
Solution 1 - C++user425495View Answer on Stackoverflow
Solution 2 - C++juanchopanzaView Answer on Stackoverflow
Solution 3 - C++Nikos AthanasiouView Answer on Stackoverflow
Solution 4 - C++andreView Answer on Stackoverflow