# typeinfo

***

**1. Type Identification**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  if (typeid(*animal) == typeid(Dog)) {
    cout << "animal is a Dog" << endl;
  }
  return 0;
}
```

**2. Dynamic Cast**

```cpp
Animal* animal = new Dog;
Dog* dog = dynamic_cast<Dog*>(animal);
if (dog) {
  cout << "Animal is a Dog" << endl;
}
```

**3. Type Comparison**

```cpp
#include <typeinfo>
if (typeid(int) == typeid(long)) {
  cout << "int and long are the same type" << endl;
}
```

**4. Type Conversion**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  Dog* dog = static_cast<Dog*>(animal);
  if (typeid(*dog) == typeid(Dog)) {
    cout << "animal is a Dog" << endl;
  }
  return 0;
}
```

**5. Type Erasure**

```cpp
#include <typeinfo>
class Animal { virtual ~Animal() {} };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  cout << typeid(*animal).name() << endl; // prints "Animal"
  delete animal;
  return 0;
}
```

**6. Type Checking**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  if (dynamic_cast<Dog*>(animal)) {
    cout << "animal is a Dog" << endl;
  }
  return 0;
}
```

**7. Type Introspection**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  cout << typeid(*animal).name() << endl; // prints "Dog"
  return 0;
}
```

**8. Type Manipulation**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  type_info& type = typeid(*animal);
  cout << type.name() << endl; // prints "Dog"
  cout << type.hash_code() << endl; // prints a unique hash code for Dog
  return 0;
}
```

**9. Type Information Retrieval**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  std::type_info& type = typeid(*animal);
  cout << type.name() << endl; // prints "Dog"
  cout << type.raw_name() << endl; // prints "class Dog"
  return 0;
}
```

**10. Type Metadata**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  std::type_info& type = typeid(*animal);
  cout << type.name() << endl; // prints "Dog"
  cout << type.hash_code() << endl; // prints a unique hash code for Dog
  cout << type.before(typeid(Animal)) << endl; // prints false
  return 0;
}
```

**11. Type Hierarchy**

```cpp
#include <typeinfo>
class Animal {
public:
  virtual void speak() { cout << "Animal speaks" << endl; }
};
class Dog : public Animal {
public:
  void speak() override { cout << "Dog barks" << endl; }
};
int main() {
  Animal* animal = new Dog;
  animal->speak(); // prints "Dog barks"
  return 0;
}
```

**12. Run-Time Type Information (RTTI)**

```cpp
#include <typeinfo>
class Animal {
public:
  virtual void speak() { cout << "Animal speaks" << endl; }
};
class Dog : public Animal {
public:
  void speak() override { cout << "Dog barks" << endl; }
};
int main() {
  Animal* animal = new Dog;
  cout << typeid(*animal).name() << endl; // prints "Dog"
  animal->speak(); // prints "Dog barks"
  return 0;
}
```

**13. Object Factory**

```cpp
#include <typeinfo>
#include <unordered_map>
class Animal {
public:
  virtual Animal* clone() = 0;
};
class Dog : public Animal {
public:
  Animal* clone() override { return new Dog; }
};
class Cat : public Animal {
public:
  Animal* clone() override { return new Cat; }
};
int main() {
  std::unordered_map<std::string, Animal* (*)(void)> animal_creators;
  animal_creators["Dog"] = Dog::clone;
  animal_creators["Cat"] = Cat::clone;
  Animal* dog = animal_creators["Dog"]();
  Animal* cat = animal_creators["Cat"]();
  return 0;
}
```

**14. Variant Type**

```cpp
#include <variant>
using namespace std;
int main() {
  variant<int, string, double> v;
  v = 10;
  if (holds_alternative<int>(v)) {
    cout << get<int>(v) << endl; // prints 10
  }
  return 0;
}
```

**15. Template Metaprogramming**

```cpp
#include <type_traits>
template <typename T>
struct IsInteger {
  static constexpr bool value = std::is_integral<T>::value;
};
int main() {
  cout << IsInteger<int>::value << endl; // prints 1
  cout << IsInteger<double>::value << endl; // prints 0
  return 0;
}
```

**16. Type Aliasing**

```cpp
#include <typeinfo>
typedef std::string MyString;
int main() {
  MyString my_string = "Hello";
  cout << typeid(my_string).name() << endl; // prints "std::string"
  return 0;
}
```

**17. Type Deduction**

```cpp
auto x = 10;
cout << typeid(x).name() << endl; // prints "int"
```

**18. Type Assertions**

```cpp
#include <typeinfo>
class Animal { };
class Dog : public Animal { };
int main() {
  Animal* animal = new Dog;
  Dog* dog = dynamic_cast<Dog*>(animal);
  if (dog) {
    cout << "animal is a Dog" << endl;
  } else {
    cout << "animal is not a Dog" << endl;
  }
  return 0;
}
```

**19. Type Conversion Operators**

```cpp
class Animal {
public:
  operator std::string() const { return "Animal"; }
};
int main() {
  Animal animal;
  std::string s = animal; // calls operator std::string()
  cout << s << endl; // prints "Animal"
  return 0;
}
```

**20. Type Deduction from Function Parameters**

```cpp
template <typename T>
void print(T value) {
  cout << value << endl;
}
int main() {
  print(10); // deduces T as int
  print("Hello"); // deduces T as std::string
  return 0;
}
```

**21. Type Deduction from Return Value**

```cpp
template <typename T>
T add(T a, T b) {
  return a + b;
}
int main() {
  int sum = add(10, 20); // deduces T as int
  double sum = add(3.14, 5.67); // deduces T as double
  return 0;
}
```

**22. Type Deduction from Templates**

```cpp
template <typename T>
class Container {
public:
  Container(T value) : value_(value) {}
  T value_;
};
int main() {
  Container c1(10); // deduces T as int
  Container c2("Hello"); // deduces T as std::string
  return 0;
}
```

**23. Type Erasure in Containers**

```cpp
#include <vector>
#include <typeinfo>
std::vector<std::any> v;
v.push_back(10);
v.push_back("Hello");
for (auto& element : v) {
  if (std::holds_alternative<int>(element)) {
    cout << std::get<int>(element) << endl; // prints 10
  } else if (std::holds_alternative<std::string>(element)) {
    cout << std::get<std::string>(element) << endl; // prints "Hello"
  }

```
