Reputation: 161
I don't know how to convert it. everything I try always fails. the code below shows it.
#include <iostream>
using namespace std;
void swaps(int &a, int &b){
int temp;
temp = a,
a=b;
b=temp;
}
int main(){
double dx = 7.7;
double dy = 9.9;
//it's ok if dx is int
//it's ok if dy is int
swaps(int(dx),int(dy)); //#1
swaps((int) dx,(int)dy); //#2
swaps(static_cast<int>(dx),static_cast<int>(dy)); //#3
return 0;
}
Upvotes: 1
Views: 891
Reputation: 3995
In this case, typecasting produces an rvalue.
See: Is it an Rvalue or Lvalue After a Cast
Passing those rvalues to a function where it is received by non-const lvalue references causes the error.
In other words, your typecasted variables are not your original variables. Therefore, it makes no sense to swap these typecasted values.
You can see this to get some picture of lvalues and rvalues in C++.
You can read this to know more about your problem:
Error: cannot bind non-const lvalue reference of type ‘int&’ to an rvalue of type ‘int’
However, the solutions suggested there are not applicable to your swap function because it must take the arguments by a non-const reference. But the rvalues produced by typecasting will not allow you to do so.
If you try to take the arguments by an rvalue reference then the code will compile but instead of swapping your original variables it will simply swap those temporary rvalues. Here is some code to illustrate this:
#include <iostream>
using namespace std;
void swap(int&& a, int&& b) // rvalue reference (universal reference)
{
cout << "Inside the swap function:-\n";
cout << "a = " << a << '\n'; // 7
cout << "b = " << b << '\n'; // 9
int tmp;
tmp = a;
a = b;
b = tmp;
// You can process the swapped variables inside the function
cout << "After Swapping:-\n";
cout << "dx = " << a << '\n'; // 9
cout << "dy = " << b << '\n'; // 7
}
int main()
{
double dx = 7.7;
double dy = 9.9;
// Now this will compile
swap(static_cast<int>(dx), static_cast<int>(dy));
// The function had swapped those temporary rvalues produced by the typecast
// So you will not have the effect of swap outside the function
cout << "Outside the swap function:-\n";
cout << "dx = " << dx << '\n'; // 7.7
cout << "dy = " << dy << '\n'; // 9.9
return 0;
}
You can check this to get started with rvalue references and move semantics.
A better solution is to use a templated swap
function instead of relying on typecast while passing the parameters:
template <typename T>
void swap(T& a, T& b)
{
T temp;
temp = a;
a = b;
b = temp;
}
You can invoke this function without typecasting your original variables, and have the effect of swap both inside and outside the function.
If you don't know what templates are then you can start from here.
By the way, C++ has a built-in swap function std::swap
. As you can see, even that relies on templates instead of typecasting to avoid problems like in your case.
Upvotes: 2
Reputation: 967
The short answer is that the reference arguments to the function swaps
need something to refer to, known as an "l-value". What if you changed the value referred to by a
? What would it be changing?
The results of int(dx)
, (int)dx
and static_cast<int>(dx)
are "prvalues" (thanks @M.M for the correction) and cannot be passed by reference.
To call swaps
you will either need to change it's signature to take a plain int
. Or cast dx
and dy
to int
variables and then pass those.
See this for gory details.
Upvotes: 2