http://gcc.gnu.org/bugzilla/show_bug.cgi?id=50785
--- Comment #9 from Jonathan Wakely <redi at gcc dot gnu.org> 2011-10-19 13:04:29 UTC --- (In reply to comment #8) > I agree that the test case should require the definition of the static member, > the actual reason being that the constraint in 3.2 p2, > > "[..] unless it is an object that satisfies the requirements for appearing in > a > constant expression [..]" The rest of the sentence is relevant: "... and the lvalue-to-rvalue conversion (4.1) is immediately applied." > is not satisfied, because the operator* of complex is not constexpr. I disagree. It is odr-used because the lvalue-to-rvalue conversions is not immediately applied. In (1*test::value) the lvalue-to-rvalue conversion is immediately applied. > Changing > the reference to std::complex by > > template<class T> > struct complex { > private: > T data[2]; > public: > constexpr complex(T r = 0, T i = 0) : data{r, i} {} > constexpr T real() { return data[0]; } > constexpr T imag() { return data[1]; } > }; > > template<class T> > constexpr complex<T> operator*(const complex<T>& lhs, const T& rhs) > { > return complex<T>(lhs.real() * rhs, lhs.imag() * rhs); > } > > also fixes the initial problem, because now the expression > > complex<double>(0,1)*test::value > > satisfies the criteria to appear in a constant expression. It is the _object_ (i.e. test:value) that needs to satisfy the criteria for appearing in a constant expression, not the expression containing it. test::value satisfies the criteria.