3

我有以下代码,一个类似数组的结构的简化:

template<typename T, size_t N>
struct X
{
    T a[N];

    template<typename... A>
    explicit X(A&&... a) : a{std::forward<A>(a)...} { }  // ERROR (2)
};

int main ()
{
    X<int,3> x;           // OK
    X<X<int,3>,2> y{x,x}; // OK
    X<X<int,3>,2> z;      // ERROR (1)
}

这在 clang 3.3 和 gcc 4.8.1 中编译良好,两者都带有-std=c++11. 我正在尝试升级 gcc,所以我现在尝试 4.9.0。在这种情况下,第三个示例 ( ERROR (1)) 实例化X的构造函数 ( ERROR (2)),此时编译器会报告

error: converting to 'X<int, 3ul>' from initializer list would use explicit
   constructor 'X<T, N>::X(A&&...) [with A = {}; T = int; long unsigned int N = 3ul]

最后一个示例尝试默认初始化数组z及其包含的数组;但是,如果我做对了,这里 gcc 基本上说包含的数组正在由 列表初始化{},这是不允许的,因为构造函数是显式的。

如果我添加以下任何一种形式的另一个默认构造函数,错误就消失了:

explicit X() {}
explicit X() : a() {}

不是

explicit X() : a{} {}

这种解决方法并不难,但是知道谁是错的,谁是对的,这样我就知道我在做什么以及为什么?

4

1 回答 1

3

这是一个 GCC 错误,PR 60417

PR 54835的旧更改旨在实施 C++ 委员会提出的修复核心问题 1518的方向。不幸的是,该更改破坏了一些有效的 C++03 程序,如 PR 60417 中的第一个示例所示。已为 PR 60417 提交了修复程序,但它仅处理某些情况。具体来说,它没有解决使用显式构造函数对类型数组进行列表初始化的情况,如在这个问题中。

于 2014-03-28T11:47:19.590 回答