(C ++)使用花括号和右值初始化时发生内部编译器错误

时间:2019-01-12 23:02:32

标签: c++ gcc c++14 internal-compiler-error

我遇到了一个奇怪的问题,该问题似乎取决于我使用的初始化语法。仅当我使用带有rvalue元素的初始化列表时,编译器才报告内部错误。

首先,我创建了一个类型来将值指定为角度。

math.hpp:

// ...
template<class S = float>
struct Angle { S value = 0, cosine = cos(value), sine = sin(value); };
// ...

接下来,一个四元数(数学对象,不是很重要),具有用于正则值和轴角形式的不同构造函数。

quaternion.hpp:

// ...
template<class S = float>
struct Quaternion {
    S w, x, y, z;
    // ...
    Quaternion(S && w = 0, S && x = 0, S && y = 0, S && z = 0):
        w(std::move(w)), x(std::move(x)), y(std::move(y)), z(std::move(z)) {}
    Quaternion(S const& w, S const& x, S const& y, S const& z):
        w(w), x(x), y(y), z(z) {}
    Quaternion(Angle<S> const& t = {0}, S const& x = 0, S const& y = 0, S const& z = 0):
        w(t.cosine), x(t.sine*x), y(t.sine*y), z(t.sine*z) {}
    template<class T> Quaternion(Quaternion<T> const& q):
        w(q.w), x(q.x), y(q.y), z(q.z) {}
    template<class T> Quaternion(Quaternion<T> && q):
        w(std::move(q.w)), x(std::move(q.x)), y(std::move(q.y)), z(std::move(q.z)) {}
    virtual ~Quaternion(void) {}
};
// ...

这就是使用中的样子-初始化角度和四元数的所有方法看起来都是有效的,但是就像我前面所描述的,只有一种方法组合会导致此内部编译器错误。

quaternion.cpp:

typedef float T;
T theta = M_PI/2;
Angle<T> a { theta }, b = { theta };
Quaternion<T> q1 = 1, q2 = {2}, q3 = {3, 4, 5, 6},
    qval1(Angle<T>{theta}, 1, 0, 0),
    // qval2 = {Angle<T>{theta}, 1, 0, 0},
    // internal compiler error: in replace_placeholders_r, at cp/tree.c:2804
    qref1(a, 1, 0, 0),
    qref2 = {a, 1, 0, 0};

我正在使用gcc版本7.3.0将其编译为C ++ 14。是什么导致错误?我应该举报吗?有解决方法,还是我应该避免使用该方法?

1 个答案:

答案 0 :(得分:1)

内部编译器错误始终是编译器中的错误。即使“应该在理论上确实起作用”,也最好避开这些区域。

我的经验是,高级初始化方法通常是编译器中的薄弱领域。测试套件似乎避免了这些。 19年前,我使用gcc使用C和命名字段初始化时遇到了类似的问题,在某些情况下会产生内部编译器错误。

尝试使用较新的编译器版本(例如gcc 8)。

如果需要代码可移植的解决方法:添加一个默认构造函数,并将所有初始化代码放入该构造函数中。只能将初始化用于简单的事情,例如普通常量值(不计算)。