0

我的情况:

我经常需要一个结构向量,其中一个字段可以被认为是一个键或 ID,而不是将它昂贵地存储在地图中(内存使用在这个应用程序中非常重要)我想将它存储在一个平面向量中但提供了一个类似地图的界面,用于按键查找元素。

我对这个问题的第一个解决方案:

template <class T, class Key, class KeyFn>
class TKeyedVector : public std::vector<T>
{
public:

    const_iterator      find(const Key& key) const {return std::find_if(begin(), end(), [&](const T& entry) {return keyFn(entry)==key; }); }

    KeyFn keyFn;
};

struct KeyedDataEntry
{
  std::string       key;
  int               value;

  struct KeyExtractor {
    const std::string& operator()(const KeyedDataEntry& e) const {return e.key; };
  };
};

using KeyedDataArray = TKeyedVector<KeyedDataEntry, std::string, KeyedDataEntry::KeyExtractor>;

现在这一切都有效,但我希望能够KeyExtractor通过使用指向嵌入类型的成员变量的指针来消除对类型的需求:

template <class T, class Key, Key T::* keyFn>
class TKeyedVector : public std::vector<T>
{
public:
        const_iterator      find(const Key& key) const {return std::find_if(begin(), end(), [&](const T& entry) {return keyFn(entry)==key; }); }
};

using KeyedDataArray = TKeyedVector<KeyedDataEntry, std::string, &KeyedDataEntry::key>;

但是我无法让它工作。我一直在寻找std::mem_fn线索的实现,但我不知道该怎么做。我得到的错误是这样的:

 warning C4353: nonstandard extension used: constant 0 as function expression.  Use '__noop' function intrinsic instead

有什么线索吗?

编辑: http: //ideone.com/Qu6TEy上的示例版本

4

2 回答 2

1

指向成员的指针需要指向成员调用语法的指针。(entry.*keyFn)()

C++17 将附带一个标准std::invoke函数,以使编写此类模板不那么烦人(它适用于所有可调用对象)。但与此同时,您需要这样做。

于 2016-09-05T16:50:51.600 回答
1

这是工作解决方案的开始。您不需要特殊的提取器对象。

请注意,我已经封装了向量。久而久之,你会后悔没有这样做。

#include <vector>
#include <string>

template <class T, class Key, const Key& (T::*Extractor)() const>
class TKeyedVector
{
    using storage = std::vector<T>;
    using const_iterator = typename storage::const_iterator;
public:

    decltype(auto) begin() const
    {
        return storage_.begin();
    }

    decltype(auto) end() const
    {
        return storage_.end();
    }

    const_iterator find(const Key& key) const
    {
        return std::find_if(begin(),
                            end(),
                            [&](const T& entry)
        {
            return entry.*Extractor() == key;
        });
    }

    storage storage_;
};

struct KeyedDataEntry
{
    std::string       key;
    int               value;

    const std::string& get_key() const { return key; }

};

int main()
{
    TKeyedVector<KeyedDataEntry, std::string, &KeyedDataEntry::get_key> mymap;

}

但是你的这个想法有问题。

为了使这个结构成为一个映射,键必须是不可变的。这主张只返回不可变对象。然后立即争论简单地使用unordered_setor set

如果您要在底层向量中返回对可变对象的引用,那么您也可以简单地使用std::find_if谓词来查找它们。

于 2016-09-05T17:06:42.767 回答