I encountered a strange issue that appears to depend on the initialization syntax I use. The compiler only reports an internal error, and only when I use an initializer list with rvalue elements.
First I made a type to designate a value as an angle.
math.hpp:
// ...
template<class S = float>
struct Angle { S value = 0, cosine = cos(value), sine = sin(value); };
// ...
Next, a quaternion (math object, not really important) with different constructors for regular values and axis-angle form.
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) {}
};
// ...
This is what it looks like in use - all of the methods of initializing both angles and quaternions look valid, but like I described earlier, only one combination of methods causes this internal compiler error.
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};
I am compiling this as C++14 with gcc version 7.3.0. What is causing the error? Should I report it? Is there a workaround, or should I just avoid that method?