Search code examples
c++functiondata-structuresstructreturn-type

Is there a way to return custom struct from a function in C++?


I wanted to know if it were possible to somehow return a custom struct from a function.

Actual use case: I have a dictionary in the form of a string, separated by some separator. Eg: a FIX message: "8=FIX.4.4,8=MKT...", while parsing this message, I want to have these key-value pairs extracted, ideally in a form of a struct: {8:FIX.4.4..}, can I have a single universal function for all messages? what data structure can be a possible return type?

The use case seems to be a fit for maps, but as the type of all the values can be different, I ruled it out. I want to get the data in their respective types, ie, int as int, string as string, seeing the key I can predetermine the expected type, eg: 34 is expected to be an integer, 8 is expected to be a string, etc. It will be great if you guys can share any ideas you have.

Thanks in advance!


Solution

  • As said in comment, you can store your data in a map of variants:

    #include <iostream>
    #include <map>
    #include <variant>
    using std::cout, std::endl;
    
    using var_t = std::variant<int, std::string, float, double>;
    
    int main()
    {
        std::map<int, var_t> myMap {
            { 10,  "hello world" },
            { 1,   5 },
            { 25,  1.0f },
            { 100, -8e20 },
        };
    
        // 1
        for (const auto& [key, value]: myMap) {
            cout << "[" << key << ": ";
            if (auto i_ptr = std::get_if<int>(&value)) {
                cout << *i_ptr;
            } else if (auto str_ptr = std::get_if<std::string>(&value)) {
                cout << *str_ptr;
            } else if (auto f_ptr = std::get_if<float>(&value)) {
                cout << *f_ptr;
            } else if (auto d_ptr = std::get_if<double>(&value)) {
                cout << *d_ptr;
            }
            cout << "]\n";
        }
    
        cout << endl << endl;
    
        // 2
        for (const auto& [key, value]: myMap) {
            std::visit([&key](auto& v) {
                cout << "[" << key << ": " << v << "]\n";
            }, value);
        }
        
        return 0;
    }
    

    https://godbolt.org/z/1PhYfq4hs

    To access your data once it's stored in a variant, you can

    1. test for each potential type with std::get_if. Using std::hold_alternative + std::get is also an option.

    or

    1. make a visitor (the lambda) and pass it to std::visit along your variant

    See: https://en.cppreference.com/w/cpp/utility/variant/