Search code examples
c++c++17variadic-templatestemplate-meta-programmingunordered-map

How to merge std::unordered_map inside std::tuple?


I want to create a class which will have an std::tuple with std::unordered_map inside. I want to create a method which will merge maps inside tuple.

#include <tuple>
#include <unordered_map>

template <typename ... Ts, std::size_t ... Is>
std::tuple<Ts...> merge_map (std::tuple<Ts...>& t1, std::tuple<Ts...> & t2, std::index_sequence<Is...> const &) { 
    return { 
        (std::get<Is>(t1).merge( std::get<Is>(t2)))... 
    }; 
}

template <class ...Ts>
struct MyContainer
{
    std::tuple<Ts...> data;

    void merge(MyContainer<Ts...>& other){
        data = merge_map(data, other.data, std::make_index_sequence<sizeof...(Ts)>{});
    }

};

int main()
{
    using namespace std;
    unordered_map<string, int> f = {{"zero", 0}, {"one", 1}};
    MyContainer <unordered_map<string, int>> container1 = {.data = f};

    unordered_map<string, int> s = {{"two", 2}, {"three", 3}};
    MyContainer <unordered_map<string, int>> container2 = {.data = s};

    container1.merge(container2);
}

But I can't compile this code. I tried to create a simple example with un std::tuple of int's and make a sum of them and it worked. But I stuck on this more complex example. Thank you for any suggestions.


Solution

  • The bigger problem I see is that std::unorderd_map<something...>::merge() return void.

    So surely is wrong

    return { 
        (std::get<Is>(t1).merge( std::get<Is>(t2)))... 
    }; 
    

    I suggest to modify merge_map(), using template folding, as follows

    template <typename ... Ts, std::size_t ... Is>
    std::tuple<Ts...> merge_map (std::tuple<Ts...> & t1,
                                 std::tuple<Ts...> & t2,
                                 std::index_sequence<Is...> const &) { 
       (std::get<Is>(t1).merge(std::get<Is>(t2)), ...); 
    
       return t1;
    }
    

    But also remember to include <string> and that the {.data = f} initialization syntax isn't C++17 (will be available starting from C++20, if I remember correctly).