whoami
whoami

Reputation: 161

How to typecast when passing argument by reference of different type

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

Answers (2)

Ardent Coder
Ardent Coder

Reputation: 3995

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.

Upvotes: 2

ChrisD
ChrisD

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

Related Questions