如何确保initializer_list不为零

时间:2019-02-19 01:08:05

标签: c++ c++11

我有一个接受initializer_list作为参数的构造函数:

A::A(std::initializer_list<uint32_t> arg)
    : vec(arg)
{
}

问题是它允许为arg设置initializer_list零或空值:

A {}

如何强制使用非零的initializer_list?

2 个答案:

答案 0 :(得分:5)

当初始化器为{}时,默认构造函数优先于std::initializer_list构造函数,但是当不存在前者时将使用后者。因此,为了强制执行编译错误,您需要显式删除默认构造函数,以便仍选择默认构造函数但不能使用它:

struct A {
    A() = delete;
    A(std::initializer_list<uint32_t>) { /* ... */ }
};

但是,在编译时,您不能阻止用户手动构造一个空的std::initializer_list对象并将其传递给您。在这种情况下,您需要引发异常以指示构造失败。

答案 1 :(得分:1)

您无法使用初始化程序列表完成此操作 -您必须进行运行时(而非编译时)验证。

但是,只是为了好玩:如果您愿意放弃初始化程序列表,并接受数组作为构造函数的输入,则可以得到想要的东西。

class A {
 private:
  std::vector<int> v_;
 public:
  template<typename T, std::size_t N>
  A(const T(&v)[N]) : v_(std::begin(v), std::end(v)) {
    static_assert(N > 0, "Requires nonempty array.");
  }
};

int main() {
  int empty_arr[] = {};
  int arr[] = {1};
  // The following no longer works as there is no constructor that takes in as
  // input an initializer list.
  // A a{1};
  // A b{};
  A c({2});
  // So does this:
  A d(arr);
  // And this would be a compilation error, even if there was no static_assert.
  // C++ standard says you can't have an array of size zero. The static_assert in 
  // the class is just to make it easier for others to see what your intention is.
  // A e(empty_arr);
}