基于范围的for循环用于私有映射值

jko*_*ian 2 c++ for-loop generator c++11

我有以下代码:

#include "stdafx.h"
#include <map>
#include <string>
#include <iostream>

class MyObject
{
public:
    MyObject()
        : m_Items{ { 1, "one" },{ 2, "two" },{ 3, "three" } }
    {}

    RETURNTYPE GetStringIterator() const
    {
        IMPLEMENTATION
    }

private:
    std::map<int, std::string> m_Items;
};


int main()
{
    MyObject o;
    for (auto& s : o.GetStringIterator())
    {
        std::cout << s;
    }
}
Run Code Online (Sandbox Code Playgroud)

什么应该RETURNTYPEIMPLEMENTATION为了允许任何客户端MyObject(在这种情况下是main()函数)迭代m_Items地图的值,而不复制任何数据?似乎这应该可以使用基于c ++ 11范围的循环和迭代器.但我无法弄清楚如何.

Oli*_*ohn 8

基于范围的迭代可以像这样实现:

class MyObject
{
public:
    MyObject()
        : m_Items{ { 1, "one" },{ 2, "two" },{ 3, "three" } }
    {}

    auto begin()       { return m_Items.begin(); }
    auto begin() const { return m_Items.begin(); }
    auto end()       { return m_Items.end(); }
    auto end() const { return m_Items.end(); }

private:
    std::map<int, std::string> m_Items;
};
Run Code Online (Sandbox Code Playgroud)

复制或不复制值取决于代码在调用站点的写入方式:

MyObject a;
for(auto [key,value] : a) {} // copies are made
for(auto & [key,value] : a) {} // no copy
for(auto const & [key,value] : a) {} // no copy
Run Code Online (Sandbox Code Playgroud)

你可以通过删除的非const版本禁用地图值的修改beginend:

class MyObject
{
public:
    MyObject()
        : m_Items{ { 1, "one" },{ 2, "two" },{ 3, "three" } }
    {}

    auto begin() const { return m_Items.begin(); }
    auto end() const { return m_Items.end(); }

private:
    std::map<int, std::string> m_Items;
};
Run Code Online (Sandbox Code Playgroud)

然后,尝试修改范围for for循环中的值将导致编译错误:

MyObject a;
for(auto & [key,value] : a) {
    //value.push_back('a');      // Not OK 
}
for(auto & [key,value] : a) {
    cout << value;             // OK
}
Run Code Online (Sandbox Code Playgroud)

请注意,如果地图是实现细节,则应使用@Barry提出的答案,因为它仅迭代地图的值,而不是关键字.