Cannot convert 'a' (type 'int') to type 'double &

I am following some C ++ tutorials and unfortunately the source material states that this particular function call cannot be made, but by no means explains why:

template<typename T>
void Swap(T &a, T &b){

    T temp;
    temp = a;
    a = b;
    b = temp;

}

      

So now I create an explicit template instantiation and pass in a

and b

;

int a = 5;
double b = 10.3;

Swap<double>(a, b);

      

Which then throws the following compiler error:

cannot convert 'a' (type 'int') to type 'double &'

My only guess is that this is due to a rule that states that r cannot be bound to a non-const reference, however, if it T &a

is just an alias, it is not the rvalue itself, is it? My implicit cast creates a temporary one that it can't bind to T &a

? Is this what's going on?

temp

- value l. It can only have a scope, but it does exist. So why not let it implicitly double-click and then assign a reference to a temp

? The intent looks pretty clear. I don't quite understand links as parameters. If a

temp is assigned, which is an lvalue, then isn't that allowed?

This means that I am even on the right track here.

Edit:

Second example:

int a = 5;
double &d = a; // invalid initialization of reference of type 'double&' from expression of type 'int'

      

However

int a = 5;
const double &d = a; //valid

      

+3


source to share


3 answers


Intuitively, swapping a

and b

must work, because the compiler can convert between int

and double

. In practice, however, think about what the compiler has to do to do what you ask.

You start with a template:

template<typename T>
void Swap(T &a, T &b){
    T temp = a;
    a = b;
    b = temp;
}

      

To instantiate for double

, the compiler creates a function like this:

void Swap(double& a, double& b) {
    double temp = a;
    a = b;
    b = temp;
}

      

These are reference parameters - they point to actual locations in memory, not aliases or copies. Under the hood, a link behaves like a pointer, so you can think of your function in a similar way if it helps:



void Swap(double* a, double *b);

      

In other words, it Swap

needs references (pointers) to two doubles in memory - two 8-byte sections of memory (assuming a double is 8 bytes). As intelligent and intuitive people, we know that an implementation Swap

doesn't really need two 8-byte sections of memory, but how it is declared and how the compiler applies it.

To create a version of Swap that can handle mixed arguments, you need to do something like this:

template<typename T1, typename T2>
void Swap(T1& a, T2& b) {
    T1 tmp(a);
    a = b;
    b = tmp;
}

      

Demo version

+5


source


What you are trying to do is effective:

int a = 5;
double& dr = a;

      

The rules governing the initialization of references in the standard are given in section 8.5. First, some definitions:

(4) For types "cv1 T1

" and "cv2 T2

", "cv1 T1

" refers to "cv2 T2

" if T1

it is the same type as T2

, or T1

is the base class T2

. "cv1 T1

" refers to "cv2 T2

" if it T1

refers to T2

, and cv1 is the same cv qualification as a higher cv qualification than cv2.

Then we have:



(5) A reference to type "cv1 T1

" is initialized with an expression of type "cv2 T2

" as follows:

  • If the reference is an lvalue reference and an initializer expression
    • is an lvalue (but not a bitfield), and "cv1 T1

      " is referentially-compatible with "cv2 T2

      ,"
    • ..

then the reference is bound to the lvalue initializer value in the first case and to the lvalue conversion result in the second case

- Otherwise, this reference must be an lvalue reference to a non-volatile const type (i.e., cv1 must be const

), or the reference must be an rvalue reference.

The "then" case does not apply because int

it is not referential-compatible with double

. So we get to another case, which says that the result must be an rvalue reference. That is, the link must be either:

const double& dcr = a; // lvalue reference to a non-volatile const type
double&& drr = a;      // rvalue reference

      

But that's not what your code is doing - hence the error. In fact, what you want to do is explicitly mentioned in the standard as a counter example at the same point:

int i = 2;
double& rd3 = i; // error: type mismatch and reference not const

      

+3


source


The compiler is looking Swap(int&, double&)

because you have supplied int

as the first parameter and double

as the second, and it cannot find it.

You can do the following:

int a = 5;
double b = 10.3;
double c = a * 1.0;
Swap<double>(a, c);

      

Essentially, you have declared a function that wants to refer to two double

s. When the compiler converts int

to double

, it creates a temp. You don't want a temporary function because it can change the value (that's what the link means).

Also makes sense to swap a floating point integer?

0


source







All Articles