Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Weird C++ template & const problem

Tags:

c++

templates

I don't understand why the output of this program is Second method instead of First Method...

#include <iostream>

template <class T>
void assign(T& t1,T& t2){
    std::cout << "First method"<< std::endl;
}

template <class T>
void assign(T& t1,const T& t2) {
    std::cout << "Second method"<< std::endl;
}

class A
{
public:
    A(int a):_a(a){};
private:
    int _a;
    friend A operator+(const A& l, const A& r);
};

A operator+(const A& l, const A& r) {
friend A operator+(const A& l, const A& r);return A(l._a+r._a);
}

int main ()
{
    A a=1;
    const A b=2;
    assign(a,a+b);
}

However, when I change my main function to this:

int main ()
{
    A a=1;
    const A b=2;
    A c=a+b;
    assign(a,c);
}

The output is First method. Any ideas?

like image 311
Andrzej Avatar asked Sep 16 '11 07:09

Andrzej


2 Answers

assign( a, a+b );

The result of a + b is an rvalue expression of type A that creates a temporary and you cannot bind it to a non-const reference, so it picks up the const overload as you are allowed to bind a const reference to a temporary.

assign( a, c );

In this case, the subexpression c is an lvalue expression and you are allowed to bind a non-const reference. In this case, because the non-const version is a perfect match with T=A it is preferred over the const overload that would require a conversion in the second argument from an lvalue of type A to const lvalue of type A.

like image 179
David Rodríguez - dribeas Avatar answered Nov 09 '22 01:11

David Rodríguez - dribeas


&t2 in your functions is taking a reference.

However, a+b cannot be bound to a normal reference, so it has to be passed as a const reference.

In your second main you're passing in a proper lvalue, so it can be modified by the function (and hence the const may change the meaning).

That's my guess, at least.

like image 26
mange Avatar answered Nov 09 '22 01:11

mange