C++ for each, pulling from vector elements

332,497

Solution 1

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

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

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++ 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);
Share:
332,497

Related videos on Youtube

Springfox
Author by

Springfox

Updated on October 02, 2020

Comments

  • Springfox
    Springfox over 3 years

    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();
            }
        }
    }
    
    • andre
      andre about 11 years
      You can use the function std::for_each
    • cprn
      cprn about 3 years
      A different approach but: std::map<int, Attack*> attacks; and in method: attacks[input]->makeDamage(); (in try catch for out_of_range exception).
  • Springfox
    Springfox about 11 years
    Ah, that's the header I was searching for then, I was hunting libraries for it. Thanks.
  • Springfox
    Springfox about 11 years
    This is such a help thanks, I've almost got it working but I need to make it return an int for the method. I'm trying, I have tried but can't work out how to do reference the pointer in the correct place on a return, could you possibly edit your answer to help with that?
  • andre
    andre about 11 years
    @Springfox You can add extra member variables to the struct if needed and access them later using f.method(...);
  • Springfox
    Springfox about 11 years
    That second one is just what I'm after actually, and more importantly I understand ;). Thanks for that, that's got it.
  • DavidO
    DavidO about 11 years
    @Justin Shrake : May want to explain why pass by reference is probably (but not always) preferable in ranged for loops, as opposed to pass by copy.
  • paulm
    paulm about 10 years
    why not std::begin/std::end on m_attack?
  • Nikos Athanasiou
    Nikos Athanasiou about 10 years
    for each is a supported extension in VS's native c++
  • Nikos Athanasiou
    Nikos Athanasiou about 10 years
    for each is a supported extension in VS's native c++
  • Nubcake
    Nubcake over 6 years
    I'm brushing up on my C++ so if you use a reference, it avoids copying the object in question? What about a pointer?
  • odalet
    odalet about 6 years
    In your first example, doesn't auto& attack implies attack.m_num and attack.makeDamage() instead of the arrow notation?