【问题标题】:C++ array wrapperC++ 数组包装器
【发布时间】:2013-05-12 21:41:49
【问题描述】:

我想要一个数组的包装器,这样,它将存储在堆栈中 - 不关心内存释放 - 可以通过大括号列表进行初始化,并且可能可以替换为普通数组的任何位置。然后,我生成了以下代码。现在我想知道,我错过了什么。 -- 那么- 这是我想要的吗?

template<class T, size_t size>
struct Array
{
    T body[size];

    operator T* () { return body; }
};

编辑:

我可能不准确。包装仅用于建筑目的。当位于初始化列表中时(主要),它应用于从大括号列表构造数组。喜欢

class A {
    protected: A(int array[])
    ...

class B : public A {
    public: B() : 
        A( (Array<int, 2>) {{ 1, 2 }} )
        ...

有一个const 版本的强制转换运算符的提议。 - 我一直在考虑这个,但不确定是否真的需要。虽然转换为const T[]是通过现有的运算符隐式完成的,并且可以通过给T = const ...定义一个常量数组,还有原因吗?

【问题讨论】:

  • 你刚刚描述了std::array
  • 你的类还应该提供operator[N]const/non-const重载。
  • @0x499602D2 [] 应该已经通过转换为指针来处理,但是关于该转换运算符的附加 const 版本的好点。

标签: c++ arrays templates


【解决方案1】:

举一个基本的例子,我认为除了一些辅助函数之外,你没有什么可以改进的。特别是,最好有一个返回大小的方法:

constexpr std::size_t size() const { return size; }

此外,还有一些其他的:

  • const/non-const 重载operator[N]

    正如@ChristianRau 在 cmets 中所述,operator T* 提供了一个-const 版本。我们可以这样实现const 版本:

    T const& operator [](std::size_t n) const
    {
        return body[n];
    }
    // similarly for non-const:
    T& operator [](std::size_t n) { return body[n]; }
    
  • begin()end() 序列器(非常有用,例如对于基于范围的 C++11):

    T* begin() { return body; }
    T* end()   { return body + size; }
    
    // const versions... very much the same
    T const* cbegin() const { return body; }
    T const* cend()   const { return body + size; }
    T const* begin()  const { return cbegin(); }
    T const* end()    const { return cend(); }
    
  • 一个at() 方法,其中包括边界检查(与约定的operator[] 相反):

    T const& at(std::size_t offset) const
    {
        // You should do bounds checking here
        return body[offset];
    }
    // also a non-const version again..
    
  • 如果有一个带有std::initializer_list&lt;T&gt; 的构造函数也很好,这样您就不必使用聚合初始化:

    #include <algorithm>
    #include <initializer_list>
    
    template <typename T, std::size_t N>
    struct Array
    {
        ...
        Array(std::initializer_list<T> const& list)
        {
            std::copy(list.begin(), list.end(), body);
        }
        ...
    };
    

    这是@DyP 建议的另一个(初始化列表总是复制,完美转发试图避免这种情况):

    template <typename T, std::size_t N>
    struct Array
    {
        ...
        template <typename... Args>
        // possibly constexpr
        Array(Args&&... args) : body{ std::forward<Args>(args)... } 
        {}
        ...
    };
    

如果你想看的话,这里是正在运行的程序 -- http://ideone.com/Zs27it#view_edit_box

您还可以包含其他功能,但正如我所说,这是一个基本示例,您最好使用类似 std::array 的东西,它或多或少具有相同的方法。

【讨论】:

  • 我认为您的第二条评论给出了更好的答案。问题确实描述了所需的功能。
  • 好吧,也许我用了太大的词。包装器不是数组的替代品,而是纯粹用于构造的工具。 - 不需要羽毛。 :)
  • 也许你想从at(std::size_t) const返回一个T const&amp;
  • IMO 带有模板参数包的 ctor 可能会更好,因为它可以使用完美转发(并且是 constexpr)。
  • 我也不明白std::array 是为什么size 不是静态成员函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多