访问地图中struct的构造函数中的键

时间:2016-06-13 08:51:56

标签: c++ dictionary

用例:记录缓冲区。这是基本的想法。 使其工作要求当元素添加到地图时,记录结构的构造函数知道用作记录编号的键。 当然,这可以通过更多代码完成,但这对我来说看起来最优雅。 最小编码:

#include <whatever>
struct record
{
    string foo;
    record(unsigned irec) { foo=readrecord(irec); }
};

map<unsigned,record>recbuf;

int main()
{
    // if the element is not yet in the map, it should be read.
    string foo_ten=recbuf[10].foo;
    // do something with the result
    printf("foo_ten: %s\n",foo_ten.c_str());
    return 0;
}

Edit1:上面的代码不起作用。 任何想法如何让这个工作? EDIT2: 我派生了一个mapplus类,添加了另一个map :: operator []:

template<class _Kty, class _Ty, class _Pr = less<_Kty>, class _Alloc = allocator<pair<const _Kty, _Ty> > >class mapplus :public map<_Kty, _Ty, _Pr, _Alloc>
{
public:
    mapped_type& operator[](const _Kty &_Keyval)
    {   // find element matching _Keyval or insert with default mapped
        iterator _Where = _Mybase::lower_bound(_Keyval);
        if (_Where == _Mybase::end()
            || _Mybase::_Getcomp()(_Keyval, _Mybase::_Key(_Where._Mynode())))

            _Where = _Mybase::emplace_hint(_Where,
                _Keyval,
                _Ty(_Keyval));
        return (_Where->second);
    }
};

这确实有效。我仍然对向我指出的评论感兴趣,我以不必要的复杂等方式做到了这一点。我有吗?可以用更少的ado来完成吗?

1 个答案:

答案 0 :(得分:0)

因此,您希望使用record构造函数构建record(unsigned)个对象,而不是默认构造函数。

很遗憾,operator[]reference)无法做到这一点:

  

如果k匹配容器中元素的键,则为函数   返回对其映射值的引用。

     

如果k与容器中任何元素的键不匹配,则   function使用该键插入一个新元素并返回一个引用   到它的映射值。请注意,这总是会增加容器   即使没有为元素分配映射值,也将大小加1   element是使用其默认构造函数构造的。

我不建议为operator[]重载std::map,对我而言,这似乎是一个糟糕的设计。

但是,您可以使用其他方法执行此操作,例如insertemplace(C ++ 11)。 例如,请参阅此答案:Using std::map<K,V> where V has no usable default constructor

经过测试的例子:

#include <map>
#include <sstream>
#include <iostream>


std::string readRecord(int id)
{
    std::stringstream stream;
    stream << id;
    return stream.str();
}

struct Record
{
    Record(int id)
        : foo(readRecord(id))
    {
    }

    std::string foo;
};

int main()
{
    std::map<int, Record> m;
    for (int i = 0; i < 10; ++i)
        m.insert(std::make_pair(i, Record(i)));

    std::cout << m.at(5).foo << std::endl;
    // std::cout << m[7].foo << std::endl;  // error 'Record::Record': no appropriate default constructor available

    return 0;
}