支持在自定义 const 原生 C++ 容器类上使用 "for each" 循环

4

我希望实现一个简单的本地C++固定容量数组模板类,支持方便的基于范围的“for each”语法,并且开销最小。

我在支持const实例时遇到了问题。

使用以下实现:

template< class T, size_t Capacity >
class List
{
public:
    List() { mSize = 0; }

    const T* begin() const { return mItems; }
    const T* end() const { return mItems + mSize; }

    T* begin() { return mItems; }
    T* end() { return mItems + mSize; }

private:
    size_t mSize;
    T mItems[ Capacity ];
};

并且这个用法:

const List< int, 5 > myInts;
for each( const int myInt in myInts )
{
    continue;
}

I get this error:

error C2440: 'initializing' : cannot convert from 'const int *' to 'int *'
    Conversion loses qualifiers

这种用法不会报错:

List< int, 5 > myInts;
for each( const int myInt in myInts )
{
    continue;
}

而这个(不好的)实现没有抱怨:

template< class T, size_t Capacity >
class List
{
public:
    List() { mSize = 0; }

    T* begin() const { return const_cast< List* >( this )->mItems; }
    T* end() const { return const_cast< List* >( this )->mItems + mSize; }

private:
    size_t mSize;
    T mItems[ Capacity ];
};

我不太理解内部发生了什么?std::vector<>是如何正确处理的?谢谢!

1个回答

2

您的用例对我来说有点奇怪,因为在您写下的C++中没有for each结构。C++11引入了常规的for和基于范围的for。我只能猜测您真正的用例是什么,但最有可能的是编译器因为const-correctness错误而发出警告。如果没有您正在尝试运行的真实代码,我无法确切地指出您的错误。无论如何,下面是一个演示两种用法的工作示例。希望它有帮助,但如果您有任何问题,请随时跟进,我会尽力解释。

#include <cstdlib>
#include <iostream>

template <typename T, std::size_t Capacity>
class List {
  public:
    List() : mSize(0) {}

    const T *begin() const { return mItems; }
    const T *end() const { return mItems + mSize; }

    T *begin() { return mItems; }
    T *end() { return mItems + mSize; }

    void add(int v)
    {
        // TODO: Check for out of range here...
        mItems[mSize++] = v;
    }

  private:
    size_t mSize;
    T      mItems[Capacity];
};

int main()
{
    /* const */ List<int, 10> array;

    array.add(1);
    array.add(11);
    array.add(15);
    array.add(3);

    // C++11 style (range-based for)
    for (int p : array) {
        std::cout << p << '\n';
    }

    // Pre C++11 style
    for (const int *from = array.begin(), *to = array.end(); from != to; ++from)
    {
        int p = *from;
        std::cout << p << '\n';
    }
}

谢谢你的时间,弗拉德。我忘了提到,“for each”似乎是最近微软编译器特有的语法糖(我不关心可移植性)。如果VS2010支持你所描述的C++11语法,我很高兴使用它——我现在不在开发机上,但我认为“for(const int p:array)”也可以正常工作?不过,我很好奇为什么“for each”对我不起作用,而且似乎找不到任何好的文档来解释。 - beau
@beau 噢,我已经谷歌了一下,似乎是在 VS 2005 中引入的非标准微软特定结构。我不能说太多关于它,因为我已经好几年没有使用 MS 编译器了...但是 VS 2010 绝对支持标准 C++11 范围 for 循环,不过你可能需要在项目设置中选择它。抱歉我在这里没什么用,我已经尽力了 ;) - user405725
1
@beau:C++11基于范围的for循环仅在VS 2012中添加。 - Blastfurnace
1
@Blastfurnace:糟糕,我的原始问题对我来说仍然非常重要。 - beau

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接