运算符'='(std :: array <T,3>和std :: initializer_list <T>)不匹配

时间:2020-10-22 07:04:12

标签: c++ arrays c++11 initializer-list

我有一个模板vec<T>类,用于恒定长度等于3的数学向量。 看起来像这样:

template <typename T>
class vec{
public:
    vec() { /**/ }

    vec(std::initializer_list<T> list) { /**/ }

private:
    std::array<T, 3> data;
};

我知道,可以通过以下方式用std::array初始化std::initializer_list

std::array<int, 3> a = {1, 2, 3};

所以我想有一个带有std::initializer_list的构造函数来像这样初始化我的向量:

vec<int> v = {1, 2, 3};

我对此也有一个解决方案:只需遍历std::initializer_list元素并写入data

vec(std::initializer_list<T> list) {
    size_t i = 0;
    for (auto it = list.begin(); it != list.end(); it++) {
        data[i++] = *it;
    }
}

我试图使构造函数看起来像这样(因为std::array的构造函数带有std::initializer_list):

vec(std::initializer_list<T> list) {
    data = list;
}

但是当我尝试编译程序时,会发生错误:

no match for ‘operator=’ (operand types are ‘std::array<int, 3>’ and ‘std::initializer_list<int>)’

这是什么问题?为什么不能用初始化器列表初始化std::array

3 个答案:

答案 0 :(得分:9)

为什么不能用初始化器列表初始化std::array

Braced-init-list和std::initializer_list不同。 (甚至std::initializer_list都可以从braced-init-list构造。)std::array是一个聚合,可以aggregate-initialized或由braced-init-list分配为

std::array<int, 3> a = {1, 2, 3};
a = {4, 5, 6}; // convert {4, 5, 6} to std::array then assign to a

请注意,{1, 2, 3}{4, 5, 6}都是括号初始列表,但不是std::initializer_list

std::array不能从std::initializer_list初始化(或分配);其构造函数和赋值运算符为implicitly-defined,并且没有这样的构造函数或赋值运算符为std::initializer_list

std::initializer_list<int> l = {1, 2, 3};
std::array<int, 3> a = l; // doesn't work
a = l;                    // doesn't work

答案 1 :(得分:4)

作为一种可能的解决方法,您可以添加带有std::array的构造函数重载,并使用构造函数初始化列表(不要与std::initializer_list混淆)来初始化data

vec(std::array<T, 3> const& list)
    : data{ list }
{
}

答案 2 :(得分:1)

您可以将std::initializer_list视为一个容器类,专门用于使用obj{args...}语法的ctor参数。

在下面,它包含一个临时c数组,其中包含size()和指向begin()end()的指针。并且std::initializer_liststd::array之间没有隐式转换。

其他帖子已经提到了实现方法,另一种方法是

std::copy(list.begin(), list.begin() + data.size(), data.begin());

即使您的list.size()大于data.size(),也可以使用此功能。

请注意,如果list.size()小于data.size(),则超出list.size()的所有内容都会被默认初始化,这将导致标量类型为ub。