提升unordered_map:不可复制无法从运算符返回引用[]
unordered_map of boost::noncopyable can't return references from operator[]
为了演示我的问题,考虑这个不能编译的简单程序:
#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创建一个新元素并返回对新元素的引用。noncopyable定义了一个(私有的)复制构造函数,但没有定义移动构造函数,因此编译器不会生成移动构造函数。在它的操作符[]中,std::unordered_map使用std::move,但由于boost::noncopyable没有定义move构造函数,因此它返回到复制构造函数。由于复制构造函数是私有的,编译失败。
是什么促使这篇文章,我试图创建一个unordered_map的boost::signal2::signal,它继承自boost::noncopyable。没有破解boost库,我可以做一个简单的解决方案吗?将信号封装在unique_ptr中是一种选择,但在我看来,我可能在这里做错了什么。
更新:
我可能发得太快了!似乎不可能向unordered_map添加boost::noncopyable的子类。Insert、operator[]和emplace都使用复制构造函数(这是私有的)或移动操作(boost::noncopyable中不存在)。对我来说,这似乎是一个主要的限制。是否有可能创建一个包含boost::noncopyable对象的unordered_map ?我明确地而不是试图复制它们——我希望它们的整个生命周期都在unordered_map中度过。
在unordered_map
中使用boost::noncopyable
的子类并非不可能,您只需为您的类型定义一个move构造函数。如果您已经创建了自己的复制构造(这是boost::noncopyable
所做的),那么c++不会创建默认的移动构造函数。另外,如果它定义了默认的move构造函数,它会尝试调用父类的copy构造函数,它是私有的。因此,您必须定义一个移动构造函数,它不会尝试调用boost::noncopyable
的复制构造函数。例如:
#include <boost/noncopyable.hpp>
#include <unordered_map>
struct foo : public boost::noncopyable
{
foo() = default;
foo(foo&&) {}
};
int main()
{
std::unordered_map<int, foo> m;
auto & element = m[0];
return 0;
}
这可能不是您想要的,但我想我应该把它扔在那里。需要注意的一点是emplace()
返回的对的second
值,这表明第二次调用没有引入新成员,也没有复制现有成员。
最后,请注意这是而不是试图解决OP使用operator []()
进行插入+访问的请求。相反,它试图简单地将boost::noncopyable
的派生构造为unordered_map<>
。要访问该标签,您可能需要以下内容的组合以及初始find()
,以确定该标签最初是否存在。
无论如何……
#include <boost/noncopyable.hpp>
#include <iostream>
#include <unordered_map>
class Foo : public boost::noncopyable
{
public:
Foo(int value) : value(value) {};
void setValue(int value) { this->value = value; }
int getValue() const { return value; }
private:
int value;
};
int main(int argc, char *argv[])
{
typedef std::unordered_map<std::string, Foo> MyMap;
MyMap mymap;
// throw ("test".1) into the map
auto p = mymap.emplace("test", 1);
auto q = mymap.emplace("test", 2); // should not overwrite the first.
// dump content
cout << p.first->second.getValue() << '(' << p.second << ')' << ' '
<< q.first->second.getValue() << '(' << q.second << ')' << endl;
// modify through the second returned iterator/bool pair.
q.first->second.setValue(3);
// dump again, see if p was also updated.
cout << p.first->second.getValue() << '(' << p.second << ')' << ' '
<< q.first->second.getValue() << '(' << q.second << ')' << endl;
return 0;
}
1(1) 1(0)
3(1) 3(0)
- 重载更少,则运算符返回相反的布尔值
- 使用重载 [] 运算符返回 std::map() 的可赋值
- 为什么我的超载"+"运算符返回的总额错误?
- (C++)为什么"||"逻辑运算符返回 1?
- 为流运算符返回代理类时解压缩参数
- C++ 运算符返回差异
- 重载运算符返回什么类型的值(对于用户定义的类型):右值还是左值?
- 运算符返回的指针的有效性 >
- 字符串流运算符>>返回值
- 动态指针引用数组由三元运算符返回值,但有异常
- 重载运算符返回的对象正在丢失 C++ 中的数据
- 如何使用设置运算符返回非 const 对象>
- 重载常量和非常量转换运算符返回数组类型时出现 MSVC 错误 C2593
- 为什么比较运算符"=="返回"YES"即使两个向量不同?
- 如何从重载的下标 [] 运算符返回 std::unique_ptr&?
- 从重载运算符返回对象>>
- 获取对运算符 [] 返回值unordered_map引用
- 我无法让这个虚拟模板化函子运算符返回正确的类型
- 为什么迭代器运算符 + 返回副本
- 从运算符[]返回对映射的char*的引用