1

I'm accessing a lot of maps in a non-performance critical piece of code. I don't want to write the usual find/!=end all the time to check for missing keys. I also don't want to use [] blindly and get default values. Is the following wrapper function smart or stupid? Is there a simpler way? Are there side effects I didn't consider?

template<typename M>
static typename M::mapped_type getMapValue(const M& m, typename M::key_type key) {

    typename M::const_iterator it = m.find(key);

    if (it != m.end()) {
        return it->second;
    } else {
        std::cerr << "Key: " << key << " not found!" << std::endl;
        std::cerr << "Returning default value." << std::endl;
        return typename M::mapped_type();
    }

}
4

5 回答 5

2

我建议使用std::map::at,然后客户端代码必须决定如何处理std::out_of_range从调用中抛出的任何异常,其中键不在映射中。

std::map<std::string, int> m;

....
int n = m.at("hello!");
于 2013-02-17T09:02:24.277 回答
1

每当 STL 接口对于某些程序逻辑变得繁琐时,我倾向于包装整个容器,而不仅仅是访问单个函数。通常,我会从现有容器类型中私下派生,并再次将我需要的部分公开。此外,我添加了我需要的实际接口,例如 operator[] 用于 const map-like 对象:

struct mycontainer:
    private map<string, string>
{
    typedef map<string, string> base;
    using base::iterator;
    using base::const_iterator;
    using base::begin;
    using base::end;

    string const& operator[](string const& k) const
    {
        const_iterator it = find(k);
        if(it == end())
            throw runtime_error("lookup failure");
        return it->second;
    }
};

笔记:

  • 如果您需要特殊的迭代器,Boost 中有一个帮助程序库可以轻松创建自定义迭代器类型。
  • 您还可以显着更改界面,例如返回默认值而不将其添加到地图或返回 boost::optional。后者是恕我直言一种轻松检查存在并一步检索值的方法。
于 2013-02-17T09:50:02.917 回答
1

如果这个想法正在检查,那么你可能想要这样的东西:

if (theMap.count(theKey)) {
  doSomethingWith(theMap[theKey]);
} else {
  doSomethingDefault();
}

名称计数非常尴尬,因为如果元素存在则返回 true,否则返回 false。我认为它应该与支持每个键多个值的某些容器一致,但后来他们从未编写过该容器。仅仅重命名“计数”“包含”可能不值得包装地图。

于 2013-02-18T18:48:39.797 回答
1

聪明的

包装std容器通常是一个好主意,因为它允许您在将来根据需要更换它们。

但是,返回默认值是正确的行为吗?它可能是你的情况,但在大多数情况下,它不会。

于 2013-02-17T08:59:46.503 回答
0

我认为你最好在找不到元素时抛出异常。无论如何,谁将监视您的程序是否会打印所有这些警告?

另外,考虑通过 const-reference 获取密钥,因为std::map确实如此。

于 2013-02-17T08:59:53.053 回答