Search code examples
c++stlcontainersstdmessage-bus

STL Container for storing multiple types of values?


I have a Message structure that I am using with a message bus, and I'd like to send data with messages. The problem is that the data will vary in type; maybe for one message I'll just want to send one int, but for another I'll want to send several ints, a string, maybe even a pointer to an object for example. I could do something like this:

struct Message {
    std::map<int, int> intPayload;
    std::map<int, std::string> strPayload;
    short id;
};

But not only is this ugly and unclean, and probably wastes space, but that doesn't account for if I want to pass a relatively exotic data type like a pointer to an instance of a class for example. What should I be using for this?


Solution

  • There are many ways to do this. Here's an example with C++17's std::variant:

    std::vector<std::variant<int, std::string>> vec1;
    
    vec1.emplace_back(1);
    vec1.emplace_back("hello"s);
    
    doSomethingWithInt( std::get<int>(vec1[0]) );
    doSomethingWithString( std::get<std::string>(vec1[1]) );
    

    vec1 is a list of element that are either int or std::string.

    You can also use a static visitor:

    std::vector<std::variant<int, std::string>> vec2;
    
    // ...
    
    for(auto&& variant : vec1) {
        variant.visit([](auto value){
            using t = decltype(value);
    
            if constexpr (std::is_same_v<t, int>) {
                std::cout << "value is a int!" << std::endl;
            } else if constexpr (std::is_same_v<t, std::string>) {
                std::cout << "value is a string!" << std::endl;
            }
        });
    }