List, Aggregate, and Designated Initialization

Heterogeneous Initializer Lists

Can std::initializer_list be used with heterogeneous data types in any way?

Abstract art representing computer programming

std::initializer_list in C++ is designed to handle homogeneous data types, meaning all elements must be of the same type. However, there are scenarios where you might want to work with heterogeneous data. Although std::initializer_list itself cannot handle heterogeneous types, there are alternative approaches to achieve similar functionality.

One common approach is to use std::tuple, which can store elements of different types:

#include <iostream>
#include <tuple>

int main() {
  std::tuple<int, double, std::string> myTuple{
    1, 2.5, "Hello"}; 
  std::cout << std::get<0>(myTuple) << ", "
            << std::get<1>(myTuple) << ", "
            << std::get<2>(myTuple);
}
1, 2.5, Hello

In this example, std::tuple allows storing an int, double, and std::string together. You can access each element using std::get<>().

If you need a container that can dynamically handle different types, consider using std::variant or a base class with pointers to derived classes:

#include <iostream>
#include <variant>
#include <vector>

int main() {
  std::vector<std::variant<
    int, double, std::string>
  > vec{1, 2.5, "Hello"}; 

  for (const auto& elem : vec) {
    std::visit([](auto&& arg) {
      std::cout << arg << ", ";
    }, elem);
  }
}
1, 2.5, Hello

std::variant can hold any one of the specified types at a time. Using std::visit, you can apply a visitor function to handle each type.

For more complex scenarios, you might use a base class with a polymorphic approach:

#include <iostream>
#include <vector>
#include <memory>

class Base {
public:
  virtual void Log() const = 0;
  virtual ~Base() = default;
};

class DerivedInt : public Base {
  int value;
public:
  DerivedInt(int val)
    : value{val} {}
  void Log() const override {
    std::cout << value << ' ';
  }
};

class DerivedDouble : public Base {
  double value;
public:
  DerivedDouble(double val)
    : value{val} {}
  void Log() const override {
    std::cout << value << ' ';
  }
};

class DerivedString : public Base {
  std::string value;
public:
  DerivedString(std::string val)
    : value{val} {}
  void Log() const override {
    std::cout << value << ' ';
  }
};

int main() {
  std::vector<std::unique_ptr<Base>> vec;
  vec.push_back(
    std::make_unique<DerivedInt>(1)
  );
  vec.push_back(
    std::make_unique<DerivedDouble>(2.5)
  );
  vec.push_back(
    std::make_unique<DerivedString>("Hello")
  );

  for (const auto& elem : vec) {
    elem->Log();
  }
}
1 2.5 Hello

This polymorphic approach allows you to store different types in a container, each derived from a common base class. This technique is flexible but requires more boilerplate code.

While std::initializer_list is limited to homogeneous types, using std::tuple, std::variant, or polymorphism provides powerful alternatives to handle heterogeneous data effectively.

This Question is from the Lesson:

List, Aggregate, and Designated Initialization

A quick guide to creating objects using lists, including std::initializer_list, aggregate and designated initialization

Answers to questions are automatically generated and may not have been reviewed.

This Question is from the Lesson:

List, Aggregate, and Designated Initialization

A quick guide to creating objects using lists, including std::initializer_list, aggregate and designated initialization

A computer programmer
Part of the course:

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Free, unlimited access

This course includes:

  • 124 Lessons
  • 550+ Code Samples
  • 96% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2024 - All Rights Reserved