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

Posted

技术标签:

【中文标题】具有私有构造函数的 unordered_map 值类型【英文标题】:unordered_map value type with private constructor 【发布时间】: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

【问题讨论】:

【参考方案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... 这可能很昂贵。 确实,在这种特殊情况下它没有帮助。

以上是关于具有私有构造函数的 unordered_map 值类型的主要内容,如果未能解决你的问题,请参考以下文章

编写Rectangle(矩形)类.该类具有double类型的私有实例变量

基类 'QAbstractListModel' 具有私有复制构造函数

具有私有构造函数和析构函数的类对象的向量?

指向具有私有构造函数的类的类成员的指针

指定构造 boost::unordered_map 时的最小桶数

C ++:如何在派生类中定义基类构造函数,如果基构造函数具有带有私有成员的初始化列表[重复]