【问题标题】:unordered_map value type with private constructor具有私有构造函数的 unordered_map 值类型
【发布时间】:2015-08-26 12:23:42
【问题描述】:

我需要以下代码:

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

【问题讨论】:

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


    【解决方案1】:

    您的错误将指向这一行:

    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 上进行第二次查找。

    【讨论】:

    • 你不需要在 myclasses 中测试 str 是否存在。 Emplace 不会添加 str 除非它不存在。
    • @Brahim 这是否正确取决于myclass 的构建成本。
    • @Barry 这个问题正在N 3873 Improved insertion interface for unique-key maps 中通过添加emplace_or_updateemplace_stable 方法或在N4006 An improved emplace() for unique-key maps 中通过更改emplace 来解决。
    • @IlyaPopov 两者都不相关,因为 make_myclass 是必须构造 myclass 的那个。不管emplace 和家人最终看起来如何,我们都必须通过myclass{}... 这可能很昂贵。
    • 确实,在这种特殊情况下它没有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-13
    相关资源
    最近更新 更多