l-value在使用std :: make_pair时指定const对象

时间:2015-10-09 13:15:00

标签: c++ stl

struct MapInserter
{
private:
    int count;

public:
    explicit MapInserter()
        : count(0)
    {
    }

    std::pair<int, std::string> operator()(std::string& value)
    {
        return std::make_pair(count++, value);
    }
};

vector<std::string> words = { "one", "two", "three","four","five" };
std::map<int, std::string> map;
MapInserter inserter;
transform(words.begin(), words.end(), map.begin(), inserter);

for (auto it = map.begin(), end = map.end(); it != end; ++it)
    cout << it->first << " : " << it->second << endl;

return 0;

这就是代码。 VS返回有关l-value specifies const object的编译错误。

单击该错误会将您移至名为utility

的文件中的以下代码
template<class _Other1,
    class _Other2>
    _Myt& operator=(pair<_Other1, _Other2>&& _Right)
    {   // assign from moved compatible pair
    first = _STD forward<_Other1>(_Right.first);
    second = _STD forward<_Other2>(_Right.second);
    return (*this);
    }

首先,我已经operator()const std::string&所以我删除了const,因为它显然是在谈论make_pair函数。但它仍然没有消失。谁能指出我这个错误是什么?

1 个答案:

答案 0 :(得分:6)

问题是std::transform()会尝试分配给目标容器的现有元素。映射的键是常量,无法分配,这就是您收到编译器错误的原因。但即使它们是,你在运行时也会得到未定义的行为,因为目标容器是空的,std::transform()期望它包含与输入范围一样多的元素。

您应该使用std::inserter()创建一个插入器迭代器,如下所示:

vector<std::string> words = { "one", "two", "three","four","five" };
std::map<int, std::string> map;
MapInserter inserter;
transform(words.begin(), words.end(), std::inserter(map, map.begin()), inserter);
//                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

这是live example

此外,在value的调用运算符中使用MapInserter字符串中的可变左值引用不是一个好主意:您不希望修改参数,所以你应该或者通过const&或者 - 我的建议 - 按值获取它,然后将其移动到返回的对中,如下所示:

std::pair<int, std::string> operator()(std::string value)
{
    return {count++, std::move(value)};
}

由于std::pair的构造函数不是explicit,因此在这种情况下您甚至不需要调用std::make_pair()