Reputation: 1874
Having a structure TB with 3 constructors, the code below compiles and the copy constructor - "Constructor A" is called twice. Commenting out "constructor C" causes compilation problem.
What is the reason for that?
Why uncommenting the const in constructor B influences the compilation result?
Is this related to overriding the default copy assignment operator?
What are the resolution rules which apply here?
int doIgetHere = 0;
struct TA{
int a;
};
struct TB{
int b;
//Constructor A
TB(TA &ta){
b = ta.a;
}
//Constructor B
TB(/*const*/ TB &tb){
doIgetHere++;
b = tb.b;
}
// Constructor C === removing this constructor cause compilation problem, why ?
TB(TB && mtb){
doIgetHere++;
b = mtb.b;
}
};
int main(){
TA ta;
TB tb1(ta); // using constructor A
TB tb2 = ta; // using constructor A
std::cout<<doIgetHere<<"\n"; // result is 0, as expected
}
Compilation log:
34:5: error: no viable constructor copying variable of type 'TB'
TB tb2 = ta; // using constructor A ^ ~~
18:2: note: candidate constructor not viable: expects an l-value for 1st argument
TB(/*const*/ TB &tb){ ^ 1 error generated.
Upvotes: 1
Views: 57
Reputation: 409136
When you do
TB tb2 = ta;
it is actually equal to
TB tb2 = TB(ta);
In other words, a temporary object is created from ta
which is then used in the copy-constructor (your constructor B).
The problem here is that non-const references can not bind to temporary objects. The solution is simply to make the argument a constant reference (which you commented out for some reason).
With your non-standard move-constructor (your constructor C) you can take temporary objects as arguments, that part of how rvalue references works.
Upvotes: 2