0

Let's say I have a Light class, and also SpotLight, PointLight and DirectionalLight which inherits from Light.

I have a map of Lights like this : std::map<std::string, Light*> LightMap;

I'd like to iterate this map for each type like this:

for ( /* each SpotLight* in LightMap */ ) { ... }

for ( /* each PointLight* in LightMap */) { ... }

etc...

How can I do that ?

thp9
  • 376
  • 2
  • 15
  • Sounds like something virtual functions would help with. – chris Jul 16 '14 at 18:47
  • @chris Yes. That's what I was thinking. There might be some circumstances where that wouldn't work, but generally a loop that called a single virtual function with different behaviour in each subclass sounds like the way to go... – JCx Jul 16 '14 at 18:50
  • 1
    If this is something that needs to be fast when iterating then I'd keep each type in its own array of pointers. Or if you can process all light types in one loop, use a virtual function and loop over them one time. – Zan Lynx Jul 16 '14 at 18:52
  • I want to retrieve data from these classes, for example I want position of PointLight, and direction of DirectionalLights, PointLight doesn't have a direction and DirectionalLight doesn't have a position etc.. I am hesitating right now, I think I'll use separate maps. – thp9 Jul 16 '14 at 18:52
  • Instead of creating separate maps, look on the high – PaulMcKenzie Jul 16 '14 at 19:25

4 Answers4

1

You can't, you'd have to iterate through each item and cast for the class type you want.

for(std::map<std::string, Light*>::iterator iter = m.begin(); iter != m.end(); iter++)
{
    if (dynamic_cast<SpotLight*>(*iter))
    {
    }
}

To avoid using dynamic cast, you could also add functions to your Light class like 'IsSpotLight' which can be overloaded by the SpotLight class to return true, etc.

You could also make separate maps for each type of light so if you need just spot lights, use the SpotLightMap mapping.

Lochemage
  • 3,974
  • 11
  • 11
1

You can use dynamic_cast and a polymorphic base class to determine which type of light you're dealing with:

#include <map>
#include <string>
#include <iostream>

class Light { public: virtual ~Light(){} }; // Light is polymorphic
class SpotLight : public Light {};
class PointLight : public Light {};
class DirectionalLight : public Light {};


int main() {
    using namespace std;
    map<string, Light*> lightmap;

    for (const auto& light : lightmap) {
        if (SpotLight* spot = dynamic_cast<SpotLight*>(light.second))
            cout << light.first << " is a spot light" << endl;
        else if (PointLight* point = dynamic_cast<PointLight*>(light.second))
            cout << light.first << " is a point light" << endl;
        else if (DirectionalLight* point = dynamic_cast<DirectionalLight*>(light.second))
            cout << light.first << " is a directional light" << endl;
        else
            cout << light.first << " is an unknown light" << endl;
    }
}
Ferruccio
  • 98,941
  • 38
  • 226
  • 299
1

I have written some code that will solve your requirement.

class Light {
    typedef enum {SpotLight, PointLight, DirectionalLight} LightTypeT;
    LightTypeT GetLightType() = 0;
};

class SpotLight : public Light {
    LightTypeT GetLightType() { return SpotLight; }
};


class PointLight : public Light {
    LightTypeT GetLightType() { return PointLight; }
};


class DirectionalLight : public Light {
    LightTypeT GetLightType() { return DirectionalLight; }
};

typedef std::map<std::string, Light*> LightMapT;

LightMapT::iterator be = light_map.begin(),
                    en = light_map.end();

for (; be != en; be++)
{
    Light * m_light = (*be).second;
    switch (m_light->GetLightType())
    {
        case SpotLight :
            {
                 // It is SpotLight
                 break;
            }
        case PointLight :
            {
                // It is PointLight
                break;
            }

        case DirectionalLight :
            {
                // It is DirectionalLight
                break;
            }
     }
}

Please let me know if it does not solve your problem. We will work on that

Abhishek Mittal
  • 356
  • 1
  • 16
0

What about something like

for ( /*each Light* lit in LightMap*/)
{
    //if lit is instance of Spotlight, do something

}

for ( /*each Light* lit in LightMap*/)
{
    //if lit is instance of PointLight, do something

}

For the C++ version of instanceof, see here

Community
  • 1
  • 1
cppprog
  • 804
  • 3
  • 12
  • 22