Гетерогенные контейнеры могут содержать элементы разных типов. Они часто используются для создания более универсальных и гибких структур данных. Примеры гетерогенных контейнеров включают std::tuple, std::variant, и контейнеры на основе boost::any.

Примеры кода

std::tuple

std::tuple позволяет хранить фиксированное количество элементов различных типов.

#include <iostream>
#include <tuple>
#include <string>
 
int main() {
    std::tuple<int, double, std::string> t(1, 2.5, "example");
 
    std::cout << std::get<0>(t) << " "; // Output: 1
    std::cout << std::get<1>(t) << " "; // Output: 2.5
    std::cout << std::get<2>(t) << std::endl; // Output: example
 
    return 0;
}

std::variant

std::variant позволяет хранить одно значение из набора типов.

#include <iostream>
#include <variant>
#include <string>
 
int main() {
    std::variant<int, double, std::string> v;
    v = 10;
    std::cout << std::get<int>(v) << std::endl; // Output: 10
 
    v = "Hello";
    std::cout << std::get<std::string>(v) << std::endl; // Output: Hello
 
    return 0;
}

boost::any

boost::any позволяет хранить значение любого типа. Для его использования требуется библиотека Boost.

#include <iostream>
#include <boost/any.hpp>
 
int main() {
    boost::any a = 10;
    std::cout << boost::any_cast<int>(a) << std::endl; // Output: 10
 
    a = std::string("Hello");
    std::cout << boost::any_cast<std::string>(a) << std::endl; // Output: Hello
 
    return 0;
}

Собственный гетерогенный контейнер

Можно создать свой гетерогенный контейнер с использованием вариативных шаблонов и наследования.

#include <iostream>
#include <memory>
#include <string>
#include <vector>
 
class Base {
public:
    virtual ~Base() = default;
    virtual void print() const = 0;
};
 
template<typename T>
class Derived : public Base {
    T value;
public:
    Derived(T val) : value(val) {}
    void print() const override {
        std::cout << value << std::endl;
    }
};
 
class HeterogeneousContainer {
    std::vector<std::unique_ptr<Base>> items;
public:
    template<typename T>
    void add(T value) {
        items.emplace_back(std::make_unique<Derived<T>>(value));
    }
 
    void printAll() const {
        for (const auto& item : items) {
            item->print();
        }
    }
};
 
int main() {
    HeterogeneousContainer container;
    container.add(10);
    container.add(3.14);
    container.add(std::string("Hello, World!"));
 
    container.printAll(); // Output: 10, 3.14, Hello, World!
 
    return 0;
}