Skip to content

Instantly share code, notes, and snippets.

@BlameOmar
Last active August 29, 2015 13:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save BlameOmar/9928711 to your computer and use it in GitHub Desktop.
Save BlameOmar/9928711 to your computer and use it in GitHub Desktop.
I wrote this because I couldn't find any practical examples, just information on dynamic_cast and typeid work. Supposedly this is because it's more taboo than goto and therefore no one should even think about using it. Obviously, I disagree.
/**
* ©2014 Omar Stefan Evans.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <iostream>
#include <string>
#include <map>
#include <typeinfo>
#include <typeindex>
class Person {
public:
Person() = default;
virtual ~Person() = default;
Person(std::string name) : name(name) {}
virtual void sayHello() = 0;
std::string getName() { return name; }
protected:
std::string name;
};
class EnglishSpeakingPerson : public Person {
public:
EnglishSpeakingPerson() = default;
EnglishSpeakingPerson(std::string name) : Person(name) {}
virtual void sayHello() {
std::cout << "Hello! I'm " << name <<".\n";
}
};
class SpanishSpeakingPerson : public Person {
public:
SpanishSpeakingPerson() = default;
SpanishSpeakingPerson(std::string name) : Person(name) {}
virtual void sayHello() {
std::cout << "¡Hola! Me llamo " << name <<".\n";
}
};
class PersonManager {
std::map<std::type_index, size_t> personArray_count;
std::map<std::type_index, size_t> personArray_size;
std::map<std::type_index, Person *> personArray_data;
public:
template <class PersonType>
void add(PersonType person) {
const std::type_index personTypeIndex = std::type_index(typeid(person));
if (personArray_data.count(personTypeIndex) == 0) {
const size_t initialSize = 1;
personArray_count[personTypeIndex] = 0;
personArray_size[personTypeIndex] = initialSize;
personArray_data[personTypeIndex] = new PersonType[initialSize];
}
size_t & count = personArray_count[personTypeIndex];
size_t & size = personArray_size[personTypeIndex];
if (count == size) {
const size_t new_size = size * 2;
PersonType * temp = new PersonType[new_size];
for (int i = 0; i < size; ++i) {
temp[i] = dynamic_cast<PersonType* >(personArray_data[personTypeIndex])[i];
}
size = new_size;
delete [] personArray_data[personTypeIndex];
personArray_data[personTypeIndex] = temp;
}
dynamic_cast<PersonType* >(personArray_data[personTypeIndex])[count++] = person;
}
void listPeople() {
for (auto pair: personArray_data) {
std::cout << "\n" << pair.first.name() << "s:\n";
Person * people = pair.second;
size_t count = personArray_count[pair.first];
for (int i = 0; i < count; ++i) {
std::cout << people[i].getName() << std::endl;
}
}
}
};
int main(int argc, const char * argv[])
{
Person *a = new EnglishSpeakingPerson("Mary");
Person *b = new SpanishSpeakingPerson("Maria");
a->sayHello();
b->sayHello();
PersonManager pm;
pm.add<EnglishSpeakingPerson>({"Carl"});
pm.add<EnglishSpeakingPerson>({"Mary"});
pm.add<EnglishSpeakingPerson>({"Robert"});
pm.add<EnglishSpeakingPerson>({"Gabrielle"});
pm.add<SpanishSpeakingPerson>({"Carlos"});
pm.add<SpanishSpeakingPerson>({"Maria"});
pm.add<SpanishSpeakingPerson>({"Roberto"});
pm.add<SpanishSpeakingPerson>({"Gabriela"});
pm.listPeople();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment