C ++初始化对象的非静态成员数组

时间:2018-07-19 11:40:24

标签: c++ arrays arduino initialization

我正在尝试不使用STL初始化类的私有成员数组(因为我正在使用的Arduino微控制器平台不支持该数组)。这意味着没有std::arraystd::initializer_list等。

以下代码可使用gcc 5.4.0和avr-gcc 4.9.2正确编译,但使用that seems to be a bug。 Clang抛出一个错误,说error: array initializer must be an initializer list(按预期)。

代码

#include <iostream>
#define PRINTFN() std::cout << __PRETTY_FUNCTION__ << std::endl

class Object {
  public:
    Object(int number) : number(number) { PRINTFN(); }
    Object(const Object &o) : number(o.number) { PRINTFN(); }
    void print() { std::cout << "The number is " << number << std::endl; }

  private:
    const int number;
};

template <size_t N>
class ManyObjects {
  public:
    ManyObjects(const Object(&objects)[N]) : objects(objects) {}
    void print() {
    for (Object &object : objects)
        object.print();
    }

  private:
    Object objects[N];
};

int main() {
    ManyObjects<3> many = {{1, 2, 3}};
    many.print();
}

输出

Object::Object(int)
Object::Object(int)
Object::Object(int)
Object::Object(const Object&)
Object::Object(const Object&)
Object::Object(const Object&)
The number is 1
The number is 2
The number is 3

初始化objects的正确方法是什么?还是在给定的约束下不可能?

3 个答案:

答案 0 :(得分:1)

您可以使用可变参数模板:

ManyObjects类中:

template <typename... _Args>
ManyObjects(_Args&&... arguments) :
    objects { arguments... }
{
}

更多here

答案 1 :(得分:0)

是的,可变参数模板可以工作,但是有点棘手:

template <size_t N>
class ManyObjects {
  public:
    template<typename T, typename ...Args>
    ManyObjects(const T& x, Args&&... args) : objects{x, args...}{}

  private:
    Object objects[N];
};

int main() {
    ManyObjects<3> many{1, 2, 3};
    ManyObjects<3> copymany{many};
    copymany.print();
}

对于任何固定的N,它可以解释为:

template <size_t N=3>
class ManyObjects {
  public:
        ManyObjects(int x, int y, int z) : objects{x, y, z}{} 
...
};

这里发生了什么:

  1. 由于构造函数Object(int)的定义,无法默认初始化对象。
  2. 对象分配运算符被隐式删除,因为数字为const
  3. 因此,必须使用聚合初始化显式地初始化任何数组Object arr[N]
  4. 我想到的唯一方法是通过可变参数模板执行扩展初始化。
  5. 要防止与副本构造函数匹配,可以在参数包之外指定第一个参数。您可以松开大小为0的结构,可以通过模板专门化来启用它。

     ManyObjects<0> noneof;
     noneof.print();
    

答案 2 :(得分:0)

我最终遵循了VTT的建议,并创建了自己的数组包装器。

如果有需要注意的事情或可能的错误等,我希望听到一些反馈。

#include <iostream>

class Object {
public:
  Object(int number) : number{number} {}
  void print() { std::cout << "The number is " << number << std::endl; }

private:
  const int number;
};

// -------------------------------------------------------------------------- //

template <class T, size_t N> class ArrayWrapper {
public:
    T &operator[](size_t index) { return data[index]; }
    const T &operator[](size_t index) const { return data[index]; }
    T *begin() { return &data[0]; }
    const T *begin() const { return &data[0]; }
    T *end() { return &data[N]; }
    const T *end() const { return &data[N]; }

  T data[N];
};

// -------------------------------------------------------------------------- //

template <size_t N> class ManyObjects {
public:
  ManyObjects(const ArrayWrapper<Object, N> &objects, const char *name)
      : objects{objects}, name{name} {}
  void print() {
    std::cout << name << std::endl;
    for (auto &object : objects)
      object.print();
  }

private:
  ArrayWrapper<Object, N> objects;
  const char *name;
};

// -------------------------------------------------------------------------- //

int main() {
    ManyObjects<3> many = {{1, 2, 3}, "Many"};
    many.print();
}