我这样做:
template<typename T> class var_accessor {
public:
std::set<std::shared_ptr<T>> varset;
std::map<std::string,std::shared_ptr<T>> vars_by_name;
std::map<uint32,std::shared_ptr<T>> vars_by_id;
std::shared_ptr<T> operator[](const uint32& index) { return vars_by_id[index]; }
std::shared_ptr<T> operator[](const std::string& index) { return vars_by_name[index]; }
bool is_in_set(std::shared_ptr<T> what) { auto it = varset.find(what); if (it == varset.end()) return false; return true; }
bool is_in_set(uint32 what) { auto it = vars_by_id.find(what); if (it == vars_by_id.end()) return false; return true; }
bool is_in_set(std::string& what) { auto it = vars_by_name.find(what); if (it == vars_by_name.end()) return false; return true; }
bool place(std::shared_ptr<T> what, const uint32 whatid, const std::string& whatstring) {
if (is_in_set(what)) return false;
varset.emplace(what);
vars_by_name.emplace(whatstring,what);
vars_by_id.emplace(whatid,what);
return true;
}
};
则...
class whatever {
std::string name;
std::function<int32()> exec;
};
和
class foo {
public:
var_accessor<whatever> stuff;
};
这有效:
std::shared_ptr<whatever> thing(new whatever);
thing->name = "Anne";
thing->exec = []() { return 1; }
foo person;
person.stuff.emplace(thing, 1, thing->name);
让名字崩溃:
std::cout << person.stuff[1]->name;
但是如果我将operator []更改为返回引用,它就可以正常工作。
我不想在不添加所有3个结构的情况下意外添加新元素,这就是我制作的原因
std::shared_ptr<T> operator[]
而不是
std::shared_ptr<T>& operator[]
有没有办法阻止下标分配,但保留下标操作符?
要明确我希望能够继续这样做
std::cout << person.stuff[4];
但是无法做到
std::shared_ptr<whatever> bob(new whatever);
bob->name = "bob";
person.stuff[2] = bob;
错误是std :: string类疯狂内的EXC_BAD_ACCESS 我读到的所有内容都只是“如果你想阻止任务,就不要返回引用”,但它也阻止了我使用它。
是的我知道有些事情应该是私密的,但我只是想让它先工作。
在XCode 5.1中使用Clang / LLVM 谢谢!
答案 0 :(得分:4)
您应该返回一个const引用。见this question
const引用意味着不允许调用者更改值,只能查看它。因此赋值将是编译时错误。但使用它会起作用(并且效率很高)。