Problem
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++.
Solution
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.