1

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;
    }

so, if you can help me in resolving the problem, I will be very grateful to you. Thank You :)

whoami
  • 92
  • 6
  • 1
    This doesn't address the question, but get in the habit of initializing objects with meaningful values rather than default-initializing them and immediately overwriting the default value. In this case, that means changing `int temp; temp = a;` to `int temp = a;`. – Pete Becker Feb 29 '20 at 14:33

2 Answers2

2

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.

ChrisD
  • 650
  • 3
  • 10
2

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.

Ardent Coder
  • 3,309
  • 9
  • 18
  • 39
  • Thanks for your answer and help me, if i could checklist both answer i'll do, hehe :) – whoami Feb 29 '20 at 08:28
  • @WhoAmI No problem. I added my answer because the existing answer suggests you to take the arguments as *plain int* or again to *use casting*, both of which are incorrect because that won't help you swap your original variables. Did you try that? – Ardent Coder Feb 29 '20 at 08:30
  • sir the only one work from answer above is changing the variable type directly, typecasting as you said just returning rvalue which is, cant reference to literal – whoami Feb 29 '20 at 09:21
  • 1
    however sir what do you mean whe you say: "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." can you show the example code? – whoami Feb 29 '20 at 09:23
  • @WhoAmI Alright, I have edited my answer to demonstrate what I meant when I said that – Ardent Coder Feb 29 '20 at 09:49
  • 1
    There is `std::swap` which should be used instead of writing your own templated swap (there are a few pitfalls) – M.M Feb 29 '20 at 10:20
  • @M.M Haha I completely forgot about that. I'll edit my answer to add this point – Ardent Coder Feb 29 '20 at 10:27