我在C ++中编写一个简单的容器类,类似于存储由键索引的对象的映射。我想提供一个访问函数,例如:
V& getValue(const K &key);
我将引用返回给值。
但是我也想处理不存在键/值并且能够向用户返回某些状态的情况(可能有一些原因导致我不希望通过它回传给调用者一些状态类型)。
我想我可以执行以下操作,但是调用它需要在调用此函数之前构造V对象,并且我只是将内部V对象复制到通过引用传入的对象中,因此这看起来很糟糕。
Status getValue(const K &key, V& v);
我也可以这样做:
V &getValue(const K &key, Status &s);
但出于某些原因,似乎有点笨重,因为焦点被从状态中吸走,用户可能忘记检查它(但也许这不是我的问题)。
无论如何都有类似
的功能Status getValue(const K &key, V& v);
在调用之前不需要构造虚拟V对象?您无法传递对引用的引用。我想我可以使用指针并且很乐意这样做,但是创建一个简单的使用和推理函数是不太可取的。
有什么想法吗?
答案 0 :(得分:2)
通常的解决方案是提供bool contains(const K &key)
函数,如果您不希望访问者以静默方式创建条目,请让它抛出异常。 (有两个访问器,一个抛出异常,另一个创建条目也很常见)
当然,这可能不是你想要的。你想把所有这些都融入一个函数的原因是什么?
答案 1 :(得分:2)
您可以使用原始函数V& getValue(const K &key)
,并抛出异常以指示未成功的Status
值。
然后,调用者可以选择延迟他们如何处理问题(通过让异常气泡到适当的处理程序),但是他们不能完全忘记它,否则程序会崩溃。呼叫站点不需要混杂状态检查和错误报告代码。
答案 2 :(得分:1)
如果您不想使用boost,我会使用boost::optional
或创建类似的模板。使用boost::optional
,您的功能将如下所示:
boost::optional<MyClass &> getValue(const K &key)
答案 3 :(得分:1)
我看到3个选项:
我个人会选择指针。
答案 4 :(得分:0)
考虑返回boost::variant<V &, Status>
或(等效)boost::variant<std::reference_wrapper<V>, Status>
。
答案 5 :(得分:0)
我会遵循std :: map界面的想法:
std::pair<iterator,bool> getValue(const K& key);
可以通过迭代器访问value对象,bool
标志显示值是否存在。
答案 6 :(得分:0)
首先我会按照书面回答你的问题:我建议你回复一个boost::optional<boost::ref<V> >
,这样你仍然可以通过引用返回,但也可以这样做。
但是,我不会建议这个界面。标准容器已经有一个解决这个问题的接口,即返回迭代器而不是值。我建议只使用一个“迭代器”接口(它不必是一个真正的完整迭代器)并在结束时返回一个end
/一个来表示找不到iter,而不是返回通过引用与否。您使容器的界面看起来越像标准容器,您使用标准算法的选择就越多,并将其插入任何您想要替换的地方。