【发布时间】:2019-06-07 10:43:35
【问题描述】:
我遇到了一个似乎取决于我使用的初始化语法的奇怪问题。编译器仅报告内部错误,并且仅在我使用带有右值元素的初始化列表时才报告。
首先我创建了一个类型来指定一个角度值。
数学.hpp:
// ...
template<class S = float>
struct Angle { S value = 0, cosine = cos(value), sine = sin(value); };
// ...
接下来是一个四元数(数学对象,不是很重要),它具有用于常规值和轴角形式的不同构造函数。
四元数.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) {}
};
// ...
这就是它在使用中的样子 - 初始化角度和四元数的所有方法看起来都有效,但就像我之前描述的那样,只有一种方法组合会导致此内部编译器错误。
四元数.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。是什么导致了错误?我应该报告吗?有没有解决方法,还是我应该避免这种方法?
【问题讨论】:
-
内部编译器错误始终是编译器错误。它不会告诉您任何有关您的代码是否正确的信息。
-
gcc 8.2.1 在 C++14 或 C++17 模式下编译,包括
qval2赋值,没有任何问题。这可能是一个已经修复的编译器错误;因此,我看到的唯一现实的选择是更新编译器,或者通过更改代码来解决错误,直到它没有失败。 -
顺便说一句,你有一个潜在的冲突,因为 2 个构造函数对所有参数都有默认值,这意味着如果没有指定,两个都是候选者。
-
如果默认构造的对象很频繁,你真的应该为
struct编写特定的构造函数,以避免调用sin(0)和cos(0)。 -
@SamVarshavchik 谢谢! (Phil1970 - 是的,那时我处于自动驾驶状态。)
标签: c++ gcc c++14 internal-compiler-error