I have some problems understanding when and if the constructor move or move assign operator is called, particularly in the context of a class with a constant data member. Consider the class
template<typename T> class A { const*T const P ;
and test program
class B { int X[100]; A<B> get_a() const { return A<B>(this); } }; int main() { B b; A<B> a = b.get_a();
then the results for compilation differ depending on the definitions provided for the move constructor and the move assignment operator in class A<> , but also for the compiler.
1 without any further declaration in class A<> (as indicated above), both g ++ (4.7.0) and icpc (13.0.1) compile the fine (with the -std=c++11 option) and produce the expected output
ctor: P=0x7fffffffd480 test: P=0x7fffffffd480
2 if I declare
A&A::operator=(A&&) = delete; A&A::operator=(const A&) = delete;
(which seems reasonable because of the constant data member that should be initialized with an initialized list), but they don't provide any further ctor, compilation fails with g ++, but in the order where icpc is. If, in addition, I define either (or both)
A::A(A&&) = default; A::A(const A&) = default;
both compilers are happy. However g ++ is unhappy with the combination
A::A(A&&) = delete; A::A(const A&) = default;
while icpc is happy.
3 If I play the same game as in 2 , except that A::A(A&&) = default; replaced by
A::A(A&&a) : P(aP) { std::cerr<<" move ctor: P="<<P<<'\n'; }
(and the equivalent for A::A(const A&) ), the results are completely identical, in particular, there is no way out of these explicit move and copy commands.
So which operator is used for = in main() ? (and why is there no result produced in the last test?)
And why is this operation allowed here at all, given that A<> has a constant data element (the results are identical if I replace the const*T const P; member const*T const P; with const T&R )?
Finally, in the case of different g ++ and icpc behaviors, which, if any, are correct?