为了演示我的问题,请考虑这个无法编译的简单程序:
#include <boost/noncopyable.hpp>
#include <unordered_map>
class foo : boost::noncopyable { };
int main()
{
std::unordered_map<int, foo> m;
auto & element = m[0];
return 0;
}
使用当前版本的 boost (1.52),Visual Studio 2012 返回错误:
cannot access private member declared in class 'boost::noncopyable_::noncopyable
.
std::unordered_map 的运算符 [] 返回对所提供键处元素的引用,乍一看似乎应该可以工作——我要求的是对元素的引用,而不是它的副本。
我对这个问题的理解是这样的(这可能是错误的,因为我有一段时间没有使用 C++)。如果未找到该键,unordered_map 将创建一个新元素并返回对新元素的引用。boost::noncopyable 定义了一个(私有)复制构造函数,但没有定义一个移动构造函数,因此编译器不会生成移动构造函数。在其 operator[] 中,std::unordered_map 使用了 std::move,但由于 boost::noncopyable 没有定义移动构造函数,所以它回退到复制构造函数。由于复制构造函数是私有的,因此编译失败。
促使这篇文章的原因是我试图创建一个 boost::signal2::signal 的 unordered_map,它继承自 boost::noncopyable。除了破解 boost 库,我能做一个简单的解决方法吗?将信号包装在 unique_ptr 中是一种选择,但在我看来,我可能在这里做错了什么。
更新:
我可能发布得太早了!似乎不可能将 boost::noncopyable 的子类添加到 unordered_map。Insert、operator[] 和 emplace 都使用复制构造函数(私有)或移动操作(对于 boost::noncopyable 不存在)。对我来说,这似乎是一个主要限制。甚至可以创建一个包含 boost::noncopyable 对象的 unordered_map 吗?我明确地不想复制它们——我希望它们在 unordered_map 中度过他们的整个生命周期。