Nir
Nir

Reputation: 1874

Constructor overloading resolution and compilation

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

Answers (1)

Some programmer dude
Some programmer dude

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

Related Questions