带有私有构造函数的unordered_map值类型

时间:2015-08-26 12:23:43

标签: c++ c++14 unordered-map

我需要以下代码:

class myclass{
    private:
        myclass(){}

        friend myclass *make_myclass(const std::string&);
};

std::unordered_map<std::string, myclass> myclasses;

myclass *make_myclass(const std::string &str){
    if(myclasses.find(str) == myclasses.end())
        myclasses.emplace(str, myclass{});
    return &myclasses[str];
}

但是编译此代码会发出一个很长的错误,即myclass()是私有的。

所以我想我会把std::pair放在一边,然后把它变成朋友:

class myclass{
    private:
        myclass(){}

        friend myclass *make_myclass(const std::string&);
        friend class std::pair<std::string, myclass>;
};

std::unordered_map<std::string, myclass> myclasses;

myclass *make_myclass(const std::string &str){
    if(myclasses.find(str) == myclasses.end())
        myclasses.emplace(
            std::piecewise_construct,
            std::forward_as_tuple(str),
            std::forward_as_tuple()
        );
    return &myclasses[str];
}

但是仍然得到关于构造函数是私有的错误。

如何让std::unordered_map的类型具有私有构造函数?

1 个答案:

答案 0 :(得分:2)

您的错误将引用此行:

return &myclasses[str];

这是因为operator[]必须默认构建一个值,如果它不在特定键的地图中。由于该运营商不是myclass的朋友,因此您会收到访问错误。

相反,您应该利用emplace返回它插入的迭代器的事实:

myclass *make_myclass(const std::string &str) {
    auto it = myclasses.find(str);
    if (it == myclasses.end()) {
        it = myclasses.emplace(str, myclass{}).first;
    }
    return &it->second;
}

这还有一个额外的好处,就是不必在str上进行第二次查找。