Reputation: 585
Firstly, this is an exercise question from the book "Programming, Principles and Practice Using C++". The books purposely told me to write these functions to understand why some of the lines cause problems. So changing the code is not an option.
I am able to send double variables or double literals as arguments to swap_v function that uses pass by value (int parameters).
I am not able to send double variables or double literals as arguments to swap_r function that uses pass by reference (int& parameters). It works when I use pass by value.
Both lines give these 3 errors.
1- a reference of type "int &" (not const-qualified) cannot be initialized with a value of type "double"
2- initial value of reference to non-const must be an lvalue
3- 'void swap_r(int &,int &)': cannot convert argument 1 from 'double' to 'int &'
#include <iostream>
void swap_v(int a, int b)
{
int temp;
temp = a;
a = b;
b = temp;
}
void swap_r(int& a, int& b)
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{
/*
int x = 7;
int y = 9;
swap_v(x, y); // Doesnt swap
swap_v(7, 9); // Cant swap literals.
const int cx = 7;
const int cy = 9;
swap_v(cx, cy); // Doesnt swap
swap_v(7.7, 9.9); // Cant swap literals.
double dx = 7.7;
double dy = 9.9;
swap_v(dx, dy); // Doesnt swap
swap_v(7.7, 9.9); // Cant swap literals.
*/
int x = 7;
int y = 9;
swap_r(x, y); // Swaps
// Doesnt compile. You have to pass variables when using pass by reference.
//swap_r(7, 9);
const int cx = 7;
const int cy = 9;
// Doesnt compile. You cant change constant values.
//swap_r(cx, cy);
// Doesnt compile. You have to pass variables when using pass by reference.
//swap_r(7.7, 9.9);
double dx = 7.7;
double dy = 9.9;
// ???
swap_r(dx, dy);
// ???
swap_r(7.7, 9.9);
}
Upvotes: 1
Views: 8772
Reputation: 122298
You can get a int
from a double
, but you cannot get a int&
from an double
.
In a nutshell, what happens here is the following:
void foo(int x) {}
double y = 5.0;
foo(y);
y
is not an int
, but a double
can be converted to an int
, so basically you have this (not really, but just to illustrate):
double y = 5.0;
int temp = y;
foo(temp);
A temporary int
is passed to the function. Now if the function takes a reference, you cannot do
void bar(int& X) {}
bar(5);
because you cannot bind 5
to a non-const reference. What would that mean? You cannot change the value of 5
. Similarly, the int
resulting from the conversion from a double
above is only temporary and passing it as non-const reference, makes no sense. Again this is not really what happens but it illustrates the "problem":
void bar(int& X) {}
double y = 5.0;
int temp = y;
bar(temp);
bar
will modify temp
, but this has no effect on y
. Because this really isnt how conversion works (you dont have a int temp=y;
explicitly in your code), the compiler forbids you also to do
double y = 5.0;
bar(y);
PS Think about how confusing it would be if something like that would be allowed:
void half(int& x) { x /= 2; }
double x = 3.2;
half(x);
What is x
now? 1.6
? 1
? The conversion from double
to int
is not the problem, but how would you get back a double
? Obviously if something like that would be allowed it would cause more confusion than it would help.
PPS swap
is not a function you should write. Use std::swap
instead.
Upvotes: 2
Reputation: 23802
This line:
swap_r(7.7, 9.9);
Cannot compile because the compiler is expecting a variable reference and you pass it a literal, this cannot be done. hence the error:
initial value of reference to non-const must be an lvalue
You also can't pass a &double
reference to an &int
refeference, so since
swap_r(dx, dy);
is passing double
variable reference to an int
reference parameter, the compilation fails with the errors:
a reference of type "int &" (not const-qualified) cannot be initialized with a value of type "double"
void swap_r(int &,int &)': cannot convert argument 1 from 'double' to 'int &
Upvotes: 1
Reputation: 434
A literal is constant. Wherever you see 3.1415, you expect it to have the value 3.1415, so the compiler will not allow you to swap its value with something else.
The meaning of const is that you name a value, e.g. Pi to 3.1415. Therefore, cx and cy are constants, not variables, so their values can't vary.
It will not allow you to call swap_r with doubles because it can't do so without introducing counter intuitive behavior. Say it converted dx to an int with the value 7, dy to an int with the value 9, swapped them, and converted them back to doubles. Rather than have dx contain 9.9 and dy contain 7.7, they'll contain 9 and 7, which isn't what a reasonable person would expect swap to do.
The language does allow passing doubles to swap_v by converting them to temporary constant ints. Those constants can be passed by value as ints, but can't be passed by reference as variables, as they would disappear at the end of the statement, which is counter intuitive. In other words - you don't expect swap to do nothing on account of the compiler throwing away temporary values it created from the variables.
Upvotes: 1
Reputation: 308
There are several problems with your code. First of all, the function void swap_v(int a, int b)
is useless, as the swap happens within the scope of the function but does not change the values outside.
Another problem is that your functions expect arguments of type int
or int&
, but you pass a double
. This will compile but it will truncate your values, as they get converted to an int. You could either overload the functions or use templates:
void swap_v(int a, int b) {...} // Gets called for ints
void swap_v(double a, double b) {...} // Gets called for doubles
template <typename T> void swap_v(T a, T b){...} // Works for all types
The second error comes from the fact, that you pass an rvalue (temporary value) to a function, which expects an lvalue:
void swap(int& a, int& b){...}
swap(7, 8);
You would need to change the signature of the function to void swap(const int& a, const int& b)
to get it to compile, but that doesn't make any sense, as you can not use the passed values outside your function.
So maybe a solution to your problem would be the following function:
template <typename T>
void swap(T& a, T& b)
{
T temp = std::move(a);
a = std::move(b);
b = std::move(temp);
}
Upvotes: 1