I came up with this class:
class Point { public: int X, Y; mutable int Z; constexpr Point(int x, int y) :X (x), Y(y), Z(0) { } constexpr int GetX() const { // Z++; // Wont compile, but following expression is valid! return X+Z; } int GetY() const { Z++; return Y; } void FoolConst() const { Z++; } }; And here is usage:
template<int S> void foo() { std::cout << S << std::endl; } int main() { constexpr Point pt(10, 20); pt.FoolConst(); char arr[pt.GetX()]; // Both compile, but GCC is using extended `new` foo<pt.GetX()>(); // GCC fails, VC compiles std::cout << sizeof(arr); // 10 (MSVC), 11 (GCC) std::cout << pt.GetX(); // 11 (MSVC), 11(GCC) } Questions:
- Why
GetXis compiling well withX+Zas return expression (Z is not constexpr). - How can I call
FoolConstandGetYmethods out ofconstexprobject (pt) ? - The behaviour of
GetXinmainis different in compilers. MSVC compiles fine with aintas template argument, while GCC (IdeOne) won't compile it.
For one compiler constexpr GetX is truly constexpr, but for other it is not if X+Z is involved. If I remove +Z and simply return X GCC is okay.
My question is very basic: If object is constexpr how can it call a non-constexpr method?
pt.FoolConst();compiles whenptisconstexpr. It may be that there is some formal UB, in which case the compilers may have the right to differ about it. But it sure does look like at least one compiler is wrong, and maybe both you tried.