【问题标题】:Method returning container for use in range-based for loop方法返回容器以用于基于范围的 for 循环
【发布时间】:2014-08-18 14:17:08
【问题描述】:

我有一个类,其中包含一些我想在方法中返回的标准容器,就像这样(只是一个例子):

class IntArray
{
public:
    IntArray(const vector<int>& vals) : vals(vals) {}

    const vector<int>& getValues() const { return vals; }
    vector<int>& getValues() { return vals; }

private:
    vector<int> vals;
};

我通过引用返回了向量以避免复制它(我不想依赖 RVO)。我不想使用 OutputIterators 来做到这一点,因为我真的想用 C++11 基于范围的 for 循环来保持简短,如下所示:

for (int val : arr.getValues()) {
    // Something
}

但是如果我想将成员变量的类型更改为list&lt;int&gt;,那么我也必须更改方法的返回类型,这可能会导致不兼容。我也不想实现begin()end() 方法,因为每个类可能有多个这样的容器。

这样做的首选方法是什么?

【问题讨论】:

  • std::beginstd::end 支持的所有类,或者具有 beginend 成员函数的类,都将由 ranged-based for loop 支持。当然这包括所有standard containers
  • 你为什么要使用这个包装器?为什么不直接返回一个 sequence,其中 sequence 包装了 vector 或 list 并提供了 .begin() 和 .end() 方法?
  • 有一篇关于这个问题的好文章here
  • @Michael:这里的 IntArray 只是一个例子。实际上,例如,我正在使用可能同时包含子网格和纹理的网格之类的东西。并且引入一个只包装这两个容器的类对我来说似乎有点沉重。

标签: c++ c++11


【解决方案1】:

您可以创建一个typedef 并在您的函数签名中引用它:

class IntArray
{
public:
    typedef std::vector<int> Vec;

    IntArray(const Vec& vals) : vals(vals) {}

    const Vec& getValues() const { return vals; }
    Vec& getValues() { return vals; }

private:
    Vec vals;
};

现在如果要更改存储类型,只需更改 typedef:

typedef std::list<int> Vec;

【讨论】:

    【解决方案2】:

    您可以使用自己的模板进行概括:

    template<typename CONTAINER>
    class IntArray
    {
        typedef CONTAINER<int> Vec;
    public:
        IntArray(const Vec& vals) : vals(vals) {}
        const Vec& getValues() const { return vals; }
        Vec& getValues() { return vals; }
    
    private:
        Vec vals;
    };
    

    现在可以随意指定容器类型了:

    std::list<int> vals { 0, 1, 2, 3, 4 };
    IntArray<std::list> arr(vals);
    for(int val: arr) {
        // Something
    }
    

    【讨论】:

      猜你喜欢
      • 2016-10-31
      • 2011-06-23
      • 1970-01-01
      • 1970-01-01
      • 2014-12-06
      • 2014-01-12
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多