【发布时间】:2014-05-06 23:42:05
【问题描述】:
我有以下代码,一个类数组结构的简化:
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{} {}
这种解决方法并不难,但知道谁错谁对,让我知道我在做什么以及为什么?
【问题讨论】:
-
最简单的解决方法是添加
X() : a{} {}(没有explicit)。我认为这与gcc.gnu.org/PR60416和open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1518有关 -
我认为这是一个 GCC 4.9 回归,我已向 bugzilla 报告,但正如 issue 1518 所示,标准并不清楚应该发生什么。
-
@JonathanWakely 真正最简单的解决方法是使用
std::array并在不重新发明轮子的情况下获得相同的功能:-P -
@MadScienceDreams No. 使用
std::array<T,N> a;代替T a[N];不会改变任何东西。问题依然存在。 -
按照从 PR60416 到 gcc.gnu.org/PR60417 的链接,您会看到原始测试用例已修复,但我添加了一个新测试用例作为评论。这是同一个问题。
标签: c++ arrays gcc c++11 list-initialization