# typeindex

***

**1. Type Identification and Checking**

```cpp
#include <type_traits>

struct A {};
struct B {};

int main() {
  std::type_index typeA = typeid(A);
  std::type_index typeB = typeid(B);

  if (typeA == typeB) {
    std::cout << "A and B are the same type" << std::endl;
  } else {
    std::cout << "A and B are different types" << std::endl;
  }
}
```

**2. Class Hierarchy Management**

```cpp
class Animal {
public:
  virtual std::type_index getTypeIndex() const = 0;
};

class Dog : public Animal {
public:
  std::type_index getTypeIndex() const override {
    return typeid(Dog);
  }
};

class Cat : public Animal {
public:
  std::type_index getTypeIndex() const override {
    return typeid(Cat);
  }
};

int main() {
  Dog dog;
  std::type_index dogType = dog.getTypeIndex();
  // ...
}
```

**3. Dynamic Casting with RTTI**

```cpp
class Base {
public:
  virtual std::type_index getTypeIndex() const = 0;
};

class Derived : public Base {
public:
  std::type_index getTypeIndex() const override {
    return typeid(Derived);
  }
};

int main() {
  Base* ptr = new Derived();

  std::type_index typeIndex = ptr->getTypeIndex();
  if (typeIndex == typeid(Derived)) {
    Derived* derivedPtr = static_cast<Derived*>(ptr);
    // ...
  }
}
```

**4. Type Introspection in Templated Code**

```cpp
template <typename T>
void printType() {
  std::cout << "Type: " << typeid(T).name() << std::endl;
}

int main() {
  printType<int>();
  printType<std::string>();
}
```

**5. Type Erasure Techniques**

```cpp
#include <functional>

template <typename T>
using Any = std::function<T()>;

int main() {
  Any<int> someValue = []() { return 42; };
  std::cout << someValue() << std::endl;
}
```

**6. Polymorphism with Variant Types**

```cpp
#include <variant>

struct A {
  int value;
};

struct B {
  std::string name;
};

using Variant = std::variant<A, B>;

int main() {
  Variant v = A{42};

  if (std::holds_alternative<A>(v)) {
    std::cout << std::get<A>(v).value << std::endl;
  }
}
```

**7. Serialization and Deserialization**

```cpp
#include <boost/serialization/type_index.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>

class MyClass {
  int x;
public:
  MyClass(int x) : x(x) {}
  template <typename Archive>
  void serialize(Archive& ar, unsigned int) {
    ar & x;
  }
};

int main() {
  MyClass myClass(42);
  boost::typeindex type = boost::typeindex::type_id<MyClass>();
}
```

**8. Dynamic Type Switching**

```cpp
enum class Type {
  A,
  B
};

struct A {
  int value;
};

struct B {
  std::string name;
};

using Visitor = std::function<void(const std::any&)>;

std::any getValue(Type type) {
  switch (type) {
    case Type::A:
      return A{42};
    case Type::B:
      return B{"John"};
  }
}

void printValue(const std::any& value) {
  std::visit([](const auto& v) {
    std::cout << "Type: " << typeid(v).name() << ", Value: " << v << std::endl;
  }, value);
}

int main() {
  auto value = getValue(Type::A);
  printValue(value);
}
```

**9. Factory Method with Type Identification**

```cpp
#include <unordered_map>

class Product {
public:
  virtual std::string getType() const = 0;
};

class ProductA : public Product {
public:
  std::string getType() const override { return "ProductA"; }
};

class ProductB : public Product {
public:
  std::string getType() const override { return "ProductB"; }
};

class Factory {
protected:
  std::unordered_map<std::string, std::function<Product*()>> products;

public:
  Factory() {
    products["ProductA"] = []() { return new ProductA(); };
    products["ProductB"] = []() { return new ProductB(); };
  }

  Product* createProduct(const std::string& type) {
    return products[type]();
  }
};

int main() {
  Factory factory;
  Product* product = factory.createProduct("ProductA");
}
```

**10. Message Passing with Type Identification**

```cpp
#include <typeinfo>

class Message {
protected:
  std::string type;

public:
  Message(const std::string& type) : type(type) {}

  virtual void handle() = 0;

  std::string getType() const { return type; }
};

class MessageA : public Message {
public:
  MessageA() : Message("MessageA") {}

  void handle() override { std::cout << "Handling MessageA" << std::endl; }
};

class MessageB : public Message {
public:
  MessageB() : Message("MessageB") {}

  void handle() override { std::cout << "Handling MessageB" << std::endl; }
};

class MessageDispatcher {
protected:
  std::unordered_map<std::string, std::function<Message*(void)>> messages;

public:
  MessageDispatcher() {
    messages["MessageA"] = []() { return new MessageA(); };
    messages["MessageB"] = []() { return new MessageB(); };
  }

  Message* dispatchMessage(const std::string& type) {
    return messages[type]();
  }
};

int main() {
  MessageDispatcher dispatcher;
  Message* message = dispatcher.dispatchMessage("MessageA");
  message->handle();
}
```

**11. Type-Safe Array Manipulation**

```cpp
#include <type_traits>
#include <vector>

template <typename T>
class TypeSafeArray {
private:
  std::vector<T> data;

public:
  static_assert(std::is_pod<T>::value, "Only POD types are supported");

  using ValueType = T;

  TypeSafeArray() = default;
  TypeSafeArray(const std::initializer_list<T>& values) : data(values) {}
  TypeSafeArray(std::size_t size, const T& value) : data(size, value) {}

  std::size_t size() const { return data.size(); }

  T& operator[](std::size_t index) { return data[index]; }
  const T& operator[](std::size_t index) const { return data[index]; }
};

int main() {
  TypeSafeArray<int> array(5, 42);
  for (int i = 0; i < array.size(); ++i) {
    std::cout << array[i] << " ";
  }
}
```

**12. Metaprogramming with Type Traits**

```cpp
#include <type_traits>

template <typename T>
struct IsSame {
  static constexpr bool value = std::is_same<T, T>::value;
};

int main() {
  std::cout << IsSame<int, int>::value << std::endl; // true
  std::cout << IsSame<int, float>::value << std::endl; // false
}
```

**13. Type-Based Function Dispatch**

```cpp
template <typename T>
void printValue(const T& value) {
  std::cout << "Type: " << typeid(T).name() << ", Value: " << value << std::endl;
}

int main() {
  printValue(42);
  printValue(std::string("Hello"));
}
```

**14. Conditional Code Execution**

```cpp
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_integral<T>::value, void> doSomething() {
  // Do something with integral types
}

template <typename T>
std::enable_if_t<std::is_floating_point<T>::value, void> doSomething() {
  // Do something with floating-point types
}

int main() {
  doSomething<int>();
  doSomething<float>();
}
```

**15. Type-Based Debugging**

```cpp
#include <iostream>
#include <typeinfo>

#define TYPE_CHECK(type) \
  if (typeid(value) != typeid(type)) { \
    std::cerr << "Type mismatch: expected " << typeid(type).name() \
              << ", got " << typeid(value).name() << std::endl; \
    exit(1); \
  }

int main() {
  int value = 42;
  TYPE_CHECK(int);
}
```

**16. Runtime Type Identification with Dynamic\_cast**

```cpp
class Shape {
public:
  virtual ~Shape() = default;
  virtual std::string getName() = 0;
};

class Square : public Shape {
public:
  std::string getName() override { return "Square"; }
};

class Circle : public Shape {
public:
  std::string getName() override { return "Circle"; }
};

int main() {
  Shape* shape = new Square();
  if (Circle* circle = dynamic_cast<Circle*>(shape)) {
    std::cout << "The shape is a circle" << std::endl;
  }
}
```

**17. Variant Type Casting**

```cpp
#include <variant>

using ShapeVariant = std::variant<Square, Circle>;

int main() {
  ShapeVariant shape = std::make_variant<Square>();
  if (std::holds_alternative<Square>(shape)) {
    std::cout << "The shape is a square" << std::endl;
  }
}
```

**18. Type-Specific Initialization**

```cpp
#include <type_traits>

struct A {
  A() { std::cout << "Initializing A" << std::endl; }
};

struct B {
  B() { std::cout << "Initializing B" << std::endl; }
};

template <typename T>
std::enable_if_t<std::is_same_v<T, A>, void> initializeA() {
  std::cout << "Initializing A using template" << std::endl;
}

template <typename T>
std::enable_if_t<std::is_same_v<T, B>, void> initializeB() {
  std::cout << "Initializing B using template" << std::endl;
}

int main() {
  initializeA<A>();
  initializeB<B>();
}
```

**19. Type-Safe Container Validation**

```cpp
#include <vector>
#include <type_traits>

template <typename Container>
std::enable_if_t<std::is_const<Container>::value, bool> isConstContainer(const Container& container) {
  return true;
}

template <typename Container>
std::enable_if_t<std::is_same<std::vector<int>, Container>::value, bool> isVectorOfInts(const Container& container) {
  return true;
}

int main() {
  const std::vector<int> vec;
  std::cout << isConstContainer(vec) << std::endl; // true
  std::cout << isVectorOfInts(vec) << std::endl; // true
}
```

**20. Type-Based Function Invocation**

```cpp
#include <initializer_list>

template <typename T>
void printValues(const std::initializer_list<T>& values) {
  for (auto value : values) {
    std::cout << value << " ";
  }
}

int main() {
  printValues({1, 2, 3, 4, 5});
}
```

**21. Type-Specific Overloading**

```cpp
#include <type_traits>

class Shape {
public:
  void draw() const { std::cout << "Drawing a shape" << std::endl; }
};

template <typename T>
std::enable_if_t<std::is_same<T, Square>::value, void> draw(const T& square) {
  std::cout << "Drawing a square" << std::endl;
}

template <typename T>
std::enable_if_t<std::is_same<T, Circle>::value, void> draw(const T& circle) {
  std::cout << "Drawing a circle" << std::endl;
}

int main() {
  Shape shape;
  Square square;
  Circle circle;

  draw(shape);
  draw(square);
  draw(circle);
}
```

**22. Type-Based Function Pointer Selection**

```cpp
#include <iostream>
#include <typeinfo>

typedef void(*TypeFcn)(void);

TypeFcn fcn;

void fcnA() { std::cout << "fcnA called" << std::endl; }
void fcnB() { std::cout << "fcnB called" << std::endl; }

int main() {
  fcn = &fcnA;
  fcn();  // Calls fcnA

  if (typeid(fcn) == typeid(&fcnA)) {
    std::cout << "fcn points to fcnA" << std::endl;
  }
}
```

**23. Type-Based Template Specialization**

```cpp
#include <type_traits>

template <typename T>
struct MyTemplate {
  static constexpr bool value = std::is_same<T, int>::value;
};

int main() {
  std::cout << MyTemplate<int>::value << std::endl; // true
}
```

**24. Type-Based Macro Expansion**

```cpp
#include <typeinfo>

#define TYPE_CHECK(type) \
  if (typeid(value) != typeid(type)) { \
    std::cerr << "Type mismatch: expected " << typeid(type).name() \
              << ", got " << typeid(value).name() << std::endl; \
    exit(1); \
  }

int main() {
  int value = 42;
  TYPE_CHECK(int);
}
```

**25. Type-Based Conditional Compilation**

```cpp
#ifdef __cplusplus
  // C++ code
#elif defined(__STDC_VERSION__)
  // C code
#else
  // Unknown platform
#endif
```

**26. Type-Based Switch Statement**

```cpp
#include <type_traits>

class Shape {
public:
  virtual ~Shape() = default;
  virtual void draw() = 0;
};

class Square : public Shape {
public:
  void draw() override { std::cout << "Drawing a square" << std::endl; }
};

class Circle : public Shape {
public:
  void draw() override { std::cout << "Drawing a circle" << std::endl; }
};

int main() {
  Shape* shape = new Square();
  switch (typeid(*shape)) {
    case typeid(Square):
      std::cout << "The shape is a square" << std::endl;
      break;
    case typeid(Circle):
      std::cout << "The shape is a circle" << std::endl;
      break;
    default:
      std::cout << "Unknown shape" << std::endl;
  }
}
```

**27. Type-Safe Hashing**

```cpp
#include <type_traits>
#include <unordered_map>

template <typename T>
std::hash<T>::result type_safe_hash(const T& value) {
  static_assert(std::is_pod<T>::value, "Only POD types are supported");
  return std::hash<T>()(value);
}

int main() {
  std::unordered_map<int, std::string> map;
  map[42] = "The answer";
}
```

**28. Type-Based Exception Handling**

```cpp
#include <typeinfo>
#include <exception>

void handleException() {
  try {
    throw std::exception();
  } catch (const std::exception& e) {
    std::cout << "Caught a standard exception: " << e.what() << std::endl;
  } catch (...) {
    std::cout << "Caught an unknown exception" << std::endl;
  }
}

int main() {
  handleException();
}
```

**29. Type-Safe Function Pointers**

```cpp
#include <type_traits>

template <typename ReturnType, typename... Args>
std::enable_if_t<std::is_same<ReturnType, void>::value, void> for_each(Args&&... args) {
  // Do something with the arguments
}

template <typename ReturnType, typename... Args>
std::enable_if_t<std::is_same<ReturnType, int>::value, int> for_each(Args&&... args) {
  // Do something else with the arguments
}

int main() {
  for_each(1, 2, 3, 4, 5);
}
```

**30. Type-Safe Function Invocation with Variadic Templates**

```cpp
#include <iostream>
#include <initializer_list>

template <typename... Args>
void print_values(const std::initializer_list<Args>& values) {
  for (auto value : values) {
    std::cout << value << " ";
  }
}

int main() {
  print_values({1, 2, 3, 4, 5});
}
```

**31. Type-Based Function Wrapping**

```cpp
#include <type_traits>

template <typename T>
std::enable_if_t<std::is_same_v<T, int>, int> add(int a, int b) {
  return a + b;
}

template <typename T>
std::enable_if_t<std::is_same_v<T, double>, double> add(double a, double b) {
  return a + b;
}

int main() {
  std::cout << add(1, 2) << std::endl; // 3
  std::cout << add(1.2, 2.3) << std::endl; // 3.5
}
```

**32. Type-Based Function Overloading**

```cpp
#include <iostream>
#include <cstdlib>

template <typename T>
void swap(T* a, T* b) {
  T temp = *a;
  *a = *b;
  *b = temp;
}

int main() {
  int *a = new int{10};
  int *b = new int{20};
  swap(a, b);
  std::cout << *a << " " << *b << std::endl; // 20 10
}
```

**33. Type-Based Function Return Value**

```cpp
#include <variant>
#include <iostream>

template <typename T>
std::variant<T, std::string> get_value(T const& value) {
  return std::variant<T, std::string>{value};
}

int main() {
  auto value = get_value(10);
  if (auto int_value = std::get_if<int>(&value)) {
    std::cout << *int_value << std::endl; // 10
  }
}
```

**34. Type-Based Function Parameter**

```cpp
#include <iostream>
#include <functional>
#include <type_traits>

template <typename F>
void call_function(F const& f) {
  if constexpr (std::is_same_v<F, std::function<void()>>) {
    f();
  }
}

int main() {
  std::function<void()> f = []() { std::cout << "Hello, world!\n"; };
  call_function(f);
}
```

**35. Type-Based Function Parameter Deduction**

```cpp
#include <iostream>

template <typename T>
auto add(T a, T b) {
  return a + b;
}

int main() {
  std::cout << add(1, 2) << std::endl; // 3
  std::cout << add(1.2, 2.3) << std::endl; // 3.5
}
```

**36. Type-Based Function Return Type Deduction**

```cpp
#include <iostream>
#include <vector>

template <typename T>
auto create_vector(int size) {
  return std::vector<T>(size);
}

int main() {
  std::vector<int> vec = create_vector<int>(5);
  std::cout << vec.size() << std::endl; // 5
}
```

**37. Type-Based Function Argument Forwarding**

```cpp
#include <iostream>

template <typename F, typename... Args>
auto forward_args(F f, Args&&... args) {
  return f(std::forward<Args>(args)...);
}

int main() {
  auto sum = [](int a, int b) { return a + b; };
  std::cout << forward_args(sum, 1, 2) << std::endl; // 3
}
```

**38. Type-Based Function Pointer Storage**

```cpp
#include <type_traits>
#include <vector>

template <typename T>
struct FunctionPointerHolder {
  void (*fptr)(T);
};

int main() {
  std::vector<FunctionPointerHolder<int>> v;
  v.push_back({[](int x) { std::cout << x << std::endl; }});
}
```

**39. Type-Based Function Pointer Invocation**

```cpp
#include <type_traits>
#include <vector>

template <typename T>
struct FunctionPointerInvoker {
  void operator()(T (*fptr)(T)) {
    (*fptr)(42);
  }
};

int main() {
  std::vector<FunctionPointerInvoker<int>> v;
  v.push_back({[](int x) { return x * 2; }});
}
```

**40. Type-Based Function Pointer Comparison**

```cpp
#include <type_traits>

int f(int x) { return x; }
int g(int x) { return x * x; }

template <typename F>
bool is_same_function_pointer(F f, F g) {
  return std::is_same<decltype(&f), decltype(&g)>::value;
}

int main() {
  std::cout << is_same_function_pointer(f, g) << std::endl; // false
}
```

**41. Type-Based Function Pointer Casting**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F, typename G>
std::enable_if_t<std::is_convertible<F*, G*>::value, G*>
cast_function_pointer(F* f) {
  return static_cast<G*>(f);
}

int main() {
  G* g = cast_function_pointer<int (*)(int), int (*)(int)>(f);
}
```

**42. Type-Based Function Pointer Initialization**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
std::enable_if_t<std::is_function<F>::value, F*>
create_function_pointer() {
  return &f;
}

int main() {
  F* g = create_function_pointer<int (*)(int)>();
}
```

**43. Type-Based Function Pointer Typeof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
std::type_info const& typeof_function_pointer(F* f) {
  return typeid(F*);
}

int main() {
  std::cout << typeof_function_pointer(&f).name() << std::endl; // "Pi*"
}
```

**44. Type-Based Function Pointer Valueof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
F* valueof_function_pointer(std::type_info const& type) {
  return static_cast<F*>(type.name());
}

int main() {
  F* g = valueof_function_pointer<int (*)(int)>(typeid(&f));
}
```

**45. Type-Based Function Pointer Assignof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
std::type_info const& assignof_function_pointer(F* f) {
  return typeid(*f);
}

int main() {
  std::cout << assignof_function_pointer(&f).name() << std::endl; // "int (int)"
}
```

**46. Type-Based Function Pointer Addrof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
F* addrof_function_pointer(std::type_info const& type) {
  return static_cast<F*>(type.name());
}

int main() {
  F* g = addrof_function_pointer<int (*)(int)>(typeid(f));
}
```

**47. Type-Based Function Pointer Subof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
std::type_info const& subof_function_pointer(F* f) {
  return typeid(*f);
}

int main() {
  std::cout << subof_function_pointer(&f).name() << std::endl; // "int (int)"
}
```

**48. Type-Based Function Pointer Derefof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
F* derefof_function_pointer(std::type_info const& type) {
  return static_cast<F*>(type.name());
}

int main() {
  F* g = derefof_function_pointer<int (*)(int)>(typeid(&f));
}
```

**49. Type-Based Function Pointer Negof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
std::type_info const& negof_function_pointer(F* f) {
  return typeid(*f);
}

int main() {
  std::cout << negof_function_pointer(&f).name() << std::endl; // "int (int)"
}
```

**50. Type-Based Function Pointer Posof**

```cpp
#include <type_traits>

int f(int x) { return x; }

template <typename F>
std::type_info const& posof_function_pointer(F* f) {
  return typeid(*f);
}

int main() {
  std::cout << posof_function_pointer(&f).name() << std::endl; // "int (int)"
}
```
