Why can't the map be initialized?

413 views Asked by At

Given the following code,

#include <iostream>
#include <string>
#include <mutex>
#include <string_view>
#include <unordered_map>

struct sstruct {
    std::string content;
    std::string_view name;
    std::mutex mtx;

    sstruct(std::string content_, std::string_view name_)
            : content(std::move(content_)), name(name_) {
    }

    std::string get_content() {
        return "";
    }
};

int main() {

    std::unordered_map<std::string, sstruct> map{
            {
                    "pippo", {"dddd", ""}
            }
    };

    std::cout << map["pippo"].content << std::endl;
}

This doesn't compile with the following error:

C:\Users\alt\Desktop\main.cpp(23): error C2440: 'initializing': cannot convert from 'initializer list' to 'std::unordered_map<std::string,sstruct,std::hash<std::string>,std::equal_to<std::string>,std::allocator<std::pair<const std::string,sstruct>>>'
C:\Users\alt\Desktop\main.cpp(27): note: No constructor could take the source type, or constructor overload resolution was ambiguous

I would like to avoid initializing the mutex in the constructor.

https://godbolt.org/z/eqKG6jac1

2

There are 2 answers

2
Vlad from Moscow On

The problem is that the class std::mutex is neither copyable nor moveable.

Consider redesigning of your class like

struct sstruct {
    std::string content;
    std::string_view name;
    static std::mutex mtx;

    sstruct(std::string content_, std::string_view name_)
            : content(std::move(content_)), name(name_) {
    }

    std::string get_content() {
        return "";
    }
};

Otherwise try something like the following

std::unordered_map<std::string, sstruct> map;

auto [it, success] = map.try_emplace( "pippo", "dddd", "" );

if ( success )
{ 
    std::cout << it->second.content << std::endl;
}

and

auto it2 = map.find( "pippo" );

if (it2 != map.end())
{
    std::cout << it2->second.content << '\n';
}

or

auto &obj = map.at( "pippo" );
std::cout << obj.content << '\n';
1
xiaofei On

unordered_map::operator[] There are two cases, the key exists time and the return value; when the key does not exist, a empty value will be inserted, and the type of the value requires a no-argument constructor