为什么这个构造函数初始化列表初始化C-array编译?

时间:2018-03-16 09:45:45

标签: c++ arrays

我自己很少使用C-arrays,但在尝试回答其他人的问题时,我想出了以下一些代码:

#include <cstddef>

template <std::size_t n>
class A {
public:
  explicit A(const int (&arr) [n]) : arr_(arr) {  }

private:
  const int arr_ [n];
};

int main(int, char**) {
  const int arr [3] = { 1, 2, 3 };
  A<3> a (arr); // (1)

  return 0;
}

它没有编译,我不期望它:

<source>:6:38: error: array initializer must be an initializer list
  explicit A(const int (&arr) [n]) : arr_(arr) {  }
                                     ^
<source>:14:8: note: in instantiation of member function 'A<3>::A' requested here
  A<3> a (arr);

我不希望它编译的原因与以下不编译相同:

int main(int, char**) {
  const int arr_a [3] = { 1, 2, 3 };
  const int arr_b [3] = arr_a;

  return 0;
}

这是编译错误:

<source>:3:13: error: array initializer must be an initializer list
  const int arr_b [3] = arr_a;
            ^

但如果您在第一个代码块中注释掉标记为(1)的行,则会编译。好像,据我所知,有一些方法可以调用A::A(const int (&) [n])有效。在我看来,即使尝试使用arr_初始化arr也是错误的。

如果您注释掉标记为(1)的行,为什么第一个代码块会编译?有没有办法打电话给A::A(const int (&) [n])有效?

2 个答案:

答案 0 :(得分:0)

它没有编译。从字面上看。您没有使用该模板,因此编译器甚至不会查看它。

答案 1 :(得分:0)

错误消息实际上比您引用的时间长一些。它也回答了你的问题:

test.cc:6:38: error: array initializer must be an initializer list
  explicit A(const int (&arr) [n]) : arr_(arr) {  }
                                     ^
test.cc:14:8: note: in instantiation of member function 'A<3>::A' requested here
  A<3> a (arr); // (1)
       ^

因此,只有模板被实例化,编译器才会真正尝试编译错误代码并发现其缺陷。因此,如果您注释掉该行,则不会产生错误。

实际上,模板的编译有点复杂,分为两个阶段。在第一阶段,基本上检查模板的印刷正确性,而实际编译到代码中只能在模板实例化的第二阶段完成。