function overloading with signed and unsigned r value reference - c++

I was trying to understanding r value reference in function overloading as in the code below.
#include <iostream>
using namespace std;
void test(int && n) {
cout << "in test int &&" << endl;
}
void test(unsigned int && n) {
cout << "in test unsigned int &&" << endl;
}
int main() {
unsigned int n = 5;
test(std::move(n)); // ---> 1
test(n); // ---> 2
test(5); // ---> 3
return 0;
}
Below is the output
in test unsigned int &&
in test int &&
in test int &&
output line 1 is expected and output line 3 is also expected as default int is signed. But didn't understand output line 2. When I call test(n), I expected it to call test(unsigned int && n) as n is unsigned instead test(int && n) is getting called. Can any one please let me know why test(int && n) is getting called.

test(n); can't use void test(unsigned int&&). The function would try to bind an rvalue reference to an lvalue.
The compiler then tries to find a match via conversion of n and finds that it can convert n to an int (which then becomes an rvalue) to get a match, hence void test(int&&) wins.

Related

if-else vs Ternary function call performance [duplicate]

This question already has answers here:
Ternary operator ?: vs if...else
(14 answers)
Closed 3 years ago.
In my C++ code, I have to select between two functions that take the same arguments based on a given condition. I could write:
if (condition)
return foo(a, b, c);
else
return bar(a, b, c);
Or:
return (condition? foo : bar)(a, b, c);
But which of these two ways is faster?
EDIT:
I tried to test using this code:
#include <cmath>
#include <chrono>
#include <iostream>
using namespace std;
void foo(float x, float y, int param)
{
pow(x+y, param);
}
void bar(float x, float y, int param)
{
pow(x+y, param);
}
int main() {
const int loops = 1000;
auto t1 = chrono::high_resolution_clock::now();
for(int i = 0; i < loops; i++)
for(int j = 0; j < loops; j++)
(i==j? foo : bar)(i, j, 2);
auto t2 = chrono::high_resolution_clock::now();
for(int i = 0; i < loops; i++)
for(int j = 0; j < loops; j++)
if(i==j)
foo(i, j, 2);
else
bar(i, j, 2);
auto t3 = chrono::high_resolution_clock::now();
cout << "ternary: " << (chrono::duration_cast<chrono::microseconds>(t2-t1).count()) << "us" << endl;
cout << "if-else: " << (chrono::duration_cast<chrono::microseconds>(t3-t2).count()) << "us" << endl;
return 0;
}
With the updated test code I got:
ternary: 70951us
if-else: 67962us
Migrated from comments:
Any decent compiler will output the same assembly for both. This is next-level premature optimization and something you shouldn't care about. Pick the one that is most readable and fits into your project style. —Sombrero Chicken
There is no problem with the performance. The compiler can generate the same object code for the both cases.
However there is a difference in applying these constructions.
For the conditional operator there must be deduced the common type of its second and third operands.
For example if you have the following functions
void foo( int, int, int ) {}
int bar( int, int, int ) { return 10; }
then you can use the if-statement as it is shown in the demonstrative program
#include <iostream>
void foo( int, int, int ) {}
int bar( int, int, int ) { return 10; }
int main()
{
int x;
std::cin >> x;
if ( x < 10 )
{
foo( x, x, x );
}
else
{
bar( x, x, x );
}
}
However you may not write as it seems an equivalent code
#include <iostream>
void foo( int, int, int ) {}
int bar( int, int, int ) { return 10; }
int main()
{
int x;
std::cin >> x;
x < 10 ? foo( x, x, x ) : bar( x, x, x );
}
because the compiler is unable to deduce the common type of the calls foo( x, x, x ) and bar( x, x, x ). The first one has the type void and the second one has the type int.
Of course you could write instead
x < 10 ? foo( x, x, x ) : ( void )bar( x, x, x );
but sometimes this makes code less readable when compound expressions are used. And moreover sometimes it is even impossible to deduce the common type because there is no explicit or implicit conversion between expressions especially for user-defined types.
Another example. You can write a function to allow the compiler to deduce its return type.
#include <iostream>
constexpr auto factorial( unsigned long long int n )
{
if ( n < 2 )
{
return n;
}
else
{
return n * factorial( n - 1 );
}
}
int main()
{
int a[factorial( 5 )];
std::cout << "The array has " << sizeof( a ) / sizeof( *a ) << " elements\n";
}
The program output is
The array has 120 elements
On the other hand, you may not write
#include <iostream>
constexpr auto factorial( unsigned long long int n )
{
return n < 2 ? n : n * factorial( n - 1 );
}
int main()
{
int a[factorial( 5 )];
std::cout << "The array has " << sizeof( a ) / sizeof( *a ) << " elements\n";
}
The compiler is unable to deduce the return type of the function.
So sometimes there is even no choice between whether to use the if-statement or the conditional expression:)

C++ combination function always resulting 0

can anybody tell me why my Combination function is always resulting 0 ?
I also tried to make it calculate the combination without the use of the permutation function but the factorial and still the result is 0;
#include <iostream>
#include <cmath>
using namespace std;
int factorial(int& n)
{
if (n <= 1)
{
return 1;
}
else
{
n = n-1;
return (n+1) * factorial(n);
}
}
int permutation(int& a, int& b)
{
int x = a-b;
return factorial(a) / factorial(x);
}
int Combination(int& a, int& b)
{
return permutation(a,b) / factorial(b);
}
int main()
{
int f, s;
cin >> f >> s;
cout << permutation(f,s) << endl;
cout << Combination(f,s);
return 0;
}
Your immediate problem is that that you pass a modifiable reference to your function. This means that you have Undefined Behaviour here:
return (n+1) * factorial(n);
// ^^^ ^^^
because factorial(n) modifies n, and is indeterminately sequenced with (n+1). A similar problem exists in Combination(), where b is modified twice in the same expression:
return permutation(a,b) / factorial(b);
// ^^^ ^^^
You will get correct results if you pass n, a and b by value, like this:
int factorial(int n)
Now, factorial() gets its own copy of n, and doesn't affect the n+1 you're multiplying it with.
While we're here, I should point out some other flaws in the code.
Avoid using namespace std; - it has traps for the unwary (and even for the wary!).
You can write factorial() without modifying n once you pass by value (rather than by reference):
int factorial(const int n)
{
if (n <= 1) {
return 1;
} else {
return n * factorial(n-1);
}
}
Consider using iterative code to compute factorial.
We should probably be using unsigned int, since the operations are meaningless for negative numbers. You might consider unsigned long or unsigned long long for greater range.
Computing one factorial and dividing by another is not only inefficient, it also risks unnecessary overflow (when a is as low as 13, with 32-bit int). Instead, we can multiply just down to the other number:
unsigned int permutation(const unsigned int a, const unsigned int b)
{
if (a < b) return 0;
unsigned int permutations = 1;
for (unsigned int i = a; i > a-b; --i) {
permutations *= i;
}
return permutations;
}
This works with much higher a, when b is small.
We didn't need the <cmath> header for anything.
Suggested fixed code:
unsigned int factorial(const unsigned int n)
{
unsigned int result = 1;
for (unsigned int i = 2; i <= n; ++i) {
result *= i;
}
return result;
}
unsigned int permutation(const unsigned int a, const unsigned int b)
{
if (a < b) return 0;
unsigned int result = 1;
for (unsigned int i = a; i > a-b; --i) {
result *= i;
}
return result;
}
unsigned int combination(const unsigned int a, const unsigned int b)
{
// C(a, b) == C(a, a - b), but it's faster to compute with small b
if (b > a - b) {
return combination(a, a - b);
}
return permutation(a,b) / factorial(b);
}
You dont calculate with the pointer value you calculate withe the pointer address.

Recursively counting a number of values that satisfies a condition and return that number

I need to count how many cubes of values between a and b (2 and 9 in this example) end with numbers between 2 and 5. Everything has to be done with recursion.
The output of this code is
part c = recc = 4
32767
0
It does not make sense to me. It calculates the value of n correctly, but then once asked to return it, returns either 0 or 32767, as if it was not defined.
Can anyone pinpoint the issue?
#include <iostream>
#include <string>
using namespace std;
void partb(int a, int b){
if(a<=b){
int p = (a*a*a)%10;
else if(p>=2 && p<=5){
cout<<a*a*a<<" ";
}
partb(a+1, b);
}
}
int recc(int n, int a, int b){
int p = (a*a*a)%10;
if(a>b){
cout<<"recc = " << n << endl;
return n;
}
else if(a<=b){
if(p>=2 && p<=5){
n++;
}
recc(n, a+1, b);
}
}
int partc(int a, int b){
int n = recc(0, a, b);
cout<<endl<< "part c = " << recc(0, a, b) << endl;
return n;
}
int main(){
int n=partc(2,9);
cout << n << endl;
return 0;
}
Not all control paths in your function return a value, so you were getting undefined behaviour when using the return value.
Now, this wasn't helped by the fact that the function itself is needlessly complicated. Let's rewrite it to use common practice for recursion:
int recc(int a, int b)
{
if (a > b) return 0;
int p = (a*a*a)%10;
int n = (p>=2 && p<=5) ? 1 : 0;
return n + recc(a+1, b);
}
Now your function is simpler. The recursion termination condition is right at the top. The function then decides whether a will contribute 1 or 0 to the count. And finally you return that value plus the count for a smaller range.
Notice how return n + recc(a+1, b); has broken the problem into a simple local solution combined with the recursive result of a reduced scope.
The invocation becomes simpler too, because you no longer have to pass in a redundant argument:
int partc(int a, int b)
{
int n = recc(a, b);
cout << endl << "part c = " << n << endl;
return n;
}

candidate function not viable: expects an l-value for 3rd argument

Calculate nth power of P (both p and n are positive integer) using a recursive function myPowerFunction(int p, int n, int &currentCallNumber). currentCallNumber is a reference parameter and stores the number of function calls made so far. myPowerFunction returns the nth power of p.
int myPowerFunction(int p, int n, int &z)
{
z++;
if(n==1)return p;
else if(n==0)return 1;
else if(n%2==0)return myPowerFunction(p,n/2,z)*myPowerFunction(p,n/2,z);
else return myPowerFunction(p,n/2,z)*myPowerFunction(p,n/2,z)*p;
}
int main()
{
cout << myPowerFunction(3,4,1);
}
You need a variable to pass as the third argument in main_program. You can't pass a constant as a non-const reference.
int count = 0;
std::cout << myPowerFunction(3, 4, count) << 'n';
std::cout << count << '\n';
Third parameter expects a lvalue, so you cannot pass numeric constant there, so possible solution can be:
int z = 1;
cout<< myPowerFunction(3,4,z);
or better to create a function that calls recursive one:
int myPowerFunction(int p, int n)
{
int z = 1;
return myPowerFunction(p,n,z);
}
In myPowerFunction(3,4,1) the literal 1 cannot be passed to a non const reference as it is a prvalue [basic.lval]. You need to store the value into a variable and then use that variable when calling the function.
int z = 0;
std::cout << myPowerFunction(3, 4, z);
You don't have to give a reference as parameter as many here state.
But yes, your input for z cannot be modified as it comes from read-only memory. Treat the input for z as const, copy z internally and give the copy as reference. Then your desired usage works:
int myPowerFunction(int p, int n, const int &z) // z is now const !
{
int _z = z + 1; // copy !
if (n == 1) return p;
else if (n == 0) return 1;
else if (n % 2 == 0) return myPowerFunction(p, n /2 , _z) * myPowerFunction(p, n / 2, _z);
else return myPowerFunction(p, n / 2, _z) * myPowerFunction(p, n / 2, _z) * p;
}
int main()
{
std::cout << myPowerFunction(3, 4, 1);
}

Jumping into C++ Chapter 13 Practice Prob No4 - Pointers

I've having trouble understanding the wording of this question and what it means by returning the second value through a pointer parameter?
The problem is:
Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter.
This is what I've done so far.
int do_math(int *x, int *y)
{
int i =*x + *y;
int u = *x * *y;
int *p_u = &u;
return i;
}
void caller()
{
int x = 10;
int y = 5;
std::cout << do_math(&x, &y);
//std::cout << *u;
}
I think all they're wanting you to do is to demonstrate your understanding of the difference between passing arguments by value and passing them by reference.
Here is a sample code that shows that although my function is only returning one value "i = X+Y", It is also changing the value of Y to (Y * X).
Of course if you do need Y's value to stay unchanged, you could use a third variable that is equal to Y's value and pass its reference as an extra argument to your function.
You could run the code bellow to see what's happening to X and Y before and after calling the function.
Hope this helps.
#include <iostream>
using namespace std;
int do_math(int value1, int *pointer_to_value2)
{
int i = value1 * *pointer_to_value2;
*pointer_to_value2 = *pointer_to_value2 + value1; // y changes here
return i;
}
int main( int argc, char ** argv ) {
int x = 10;
int y = 5;
cout << "X before function call " << x << endl;
cout << "Y before function call " << y << endl;
int product = do_math(x, &y);
cout << "X after function call " << x << endl;
cout << "Y after function call " << y << endl;
cout << "What the function returns " << product << endl;
return 0;
}
In the assignment there is written
Write a function that takes input arguments ...
So there is no any need to declare these input parameters as pointers.
The function could look like
int do_math( int x, int y, int &sum )
{
sum = x + y;
return x * y;
}
or
int do_math( int x, int y, int *sum )
{
*sum = x + y;
return x * y;
}
In these function definitions the sum and the product can be exchanged as the parameter and return value
As for me the I would write the function either as
void do_math( int x, int y, long long &sum, long long &product )
{
sum = x + y;
product = x * y;
}
or
#include <utility>
//...
std::pair<long long, long long> do_math( int x, int y )
{
return std::pair<long long, long long>( x + y, x * y );
}
void caller()
{
int x = 10;
int y = 5;
std::pair<long long, long long> result = do_math( x, y );
std::cout << "Sum is equal to " << result.first
<< " and product is equal to " << result.second
<< std::endl;
}
Edit: I would like to explain why this statement
std::cout << "sum is " << do_math(x, y, result) << " and result is " << result;
is wrong.
The order of evaluation of subexpressions and function argument is unspecified. So in the statement above some compilers can output value of result before evaluation function call do_math(x, y, result)
So the behaviour of the program will be unpredictable because you can get different results depending on using the compiler.
Edit: As for your code from a comment then it should look like
#include <iostream>
int do_math( int x, int y, int *p_u )
{
int i = x + y;
*p_u = x * y;
return i;
}
int main()
{
int x = 10;
int y = 5;
int u;
int i = do_math( x, y, &u );
std::cout << i << std::endl;
std::cout << u << std::endl;
}
Also take into account that in general case it is better to define variables i and u as having type long long because for example the product of two big integers can not fit in an object of type int.
The wording is kind of contrived but I believe the task asks you to
return the multiplication as the return value of the function, and
since you can't return two types at once (except if you wrap them up somehow), you should use a third parameter as a storage area for the sum:
#include <iostream>
/* Multiplication in here */ int do_math(int x, int y, int& result/* Addition in here */)
{
result = x + y;
return x*y;
}
int main() {
int x = 10;
int y = 5;
int addition = 0;
int multiplication = do_math(x, y, addition);
std::cout << "multiplication is " << multiplication << " and sum is " << addition;
}
Example
It's not specifically asking you to use two parameters for the function.
A typical solution to the intent of the exercise text…
” Write a function that takes input arguments and provides two seperate results to the caller, one that is the result of multiplying the two argumentsm the other the result of adding them. Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is
auto product_and_sum( double& sum, double const a, double const b )
-> double
{
sum = a + b;
return a*b;
}
#include <iostream>
using namespace std;
auto main() -> int
{
double product;
double sum;
product = product_and_sum( sum, 2, 3 );
cout << product << ", " << sum << endl;
}
This code is unnatural in that one result is returned while the other is an out-argument.
It's done that way because the exercise text indicates that one should do it that way.
A more natural way to do the same is to return both, as e.g. a std::pair:
#include <utility> // std::pair, std::make_pair
using namespace std;
auto product_and_sum( double const a, double const b )
-> pair<double, double>
{
return make_pair( a*b, a+b );
}
#include <iostream>
#include <tuple> // std::tie
auto main() -> int
{
double product;
double sum;
tie( product, sum ) = product_and_sum( 2, 3 );
cout << product << ", " << sum << endl;
}
As the second program illustrates, the last sentence of the exercise text,
” Since you can directly return only one value from a funciton you'll need the seecond value to be returned through a pointer or references paramter
… is just not true. I suspect the author had meant the word “directly” to clarify that this excluded the case of a non-basic type. But even so the conclusion is incorrect.
What you need to do is provide another parameter to the function - the pointer or the reference to the variable where you want to store your other result:
int do_math(int *x, int *y, int &res) //or int *res
{
...
res = *x * *y;
...
}
Then make a result variable in main and pass it to the function