I have a class with a constexpr
value constructor, but no copy or move ctor
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
};
int main() {
constexpr C arr[] = {1, 2};
}
I've found that this code doesn't work because it's actually trying to use the move constructor for C
rather than the value constructor to construct in place. One issue is that I want this object to be unmovable (for test purposes) but I thought "okay, fine, I'll add a move constructor."
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
C& operator=(C&&) = delete;
C(C&&) { /*something*/ } // added, assume this must be non trivial
};
Okay fine, now it uses the move constructor and everything works under gcc but when I use clang, it complains because the move constructor is not marked constexpr
error: constexpr variable 'arr' must be initialized by a constant expression
constexpr C arr[] = {1, 2};
If I mark the move constructor constexpr
it works under gcc and clang, but the issue is that I want to have code in the move constructor if it runs at all, and constexpr constructors must have empty bodies. (The reason for my having code in the move ctor isn't worth getting into).
So who is right here? My inclination is that clang would be correct for rejecting the code.
NOTE
It does compile with initializer lists and non-copyable non-movable objects as below:
class C {
public:
constexpr C(int) { }
C(const C&) = delete;
C& operator=(const C&) = delete;
C& operator=(C&&) = delete;
C(C&&) = delete;
};
int main() {
constexpr C arr[] = {{1}, {2}};
}
My main concern is which compiler above is correct.