c++ implicit type conversion string -> int? - c++

I was just working on c++ types, when i just thought of trying out the following program.
void swap(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
int main(){
string a{"sssss"}, b{"ddddd"};
swap(a,b); //this should not work!! but it does
cout << a << ' '<<b <<endl;
return 0;
}
I was not expecting this to swap the strings, but it does! Why is this working? Although the compiler raises warnings, it is not an error!

Your program does not compile. I am guessing that you actually had the following lines but failed to post them:
#include <iostream>
#include <string>
using namespace std;
There is a standard template std::swap. Although this is in #include <algorithm>, any header may include any other header. So even if you didn't include this specifically, it may have gotten included anyway.
So when you call an unqualified swap, both your swap and std::swap are included in overload resolution. (Even if you didn't have using namespace std;, namespace std is still searched because of ADL, since the arguments are of type std::string which is in namespace std).
To avoid this happening, you could put your swap in a named namespace, and use the qualified name (e.g. mystuff::swap(a, b);).

// Assuming the following:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
// or even using namespace std, though this
// would make std::swap a candidate even
// without ADL
// renaming shows that it's not this function
// that gets called ...
void myswap(int& a, int& b) {
int temp = a;
a = b;
b = temp;
// printing some output also reveals what's going on
}
int main() {
string a{"sssss"}, b{"ddddd"};
swap(a,b); // this is not calling your swap!
// myswap(a,b) produces the error you expected
cout << a << ' '<< b <<endl;
return 0;
}
It's not calling your swap function. Namespaces are kind of interfaces, so when one declares free functions to be in the same namespace as the data types they operate on, then calling them without proper namespace qualification will work.
This is called "argument dependent name lookup", or ADL.
So when you call the function swap on a std::string, it'll also look for candidates in the std namespace. And since there's std::swap, which can be applied to strings and no other candidate in your global namespace (since your swap only operates on integers) it'll use it for the call.
As I showed above you can make your function produce debugging output or rename it to easily verify that it's not your function that is called.
As a side note: Suppose there were some kind of implicit conversion from string to int. You'd then get two temporaries. Then your swap function would get called (not in reality, since binding non const references to temporaries isn't allowed) and these integers exchanged. And then? This wouldn't have any effect on the original strings.
Finally, I wouldn't count this code as portable. It only compiles when either the header string or iostream includes the algorithm header, and one of these three provides the specialisation of std::swap for strings. But since this doesn't seem to be guaranteed by the standard, this code would only reliably work when including algorithm yourself.

Related

Can I use a std::string variable as an argument to an operator?

For example, if I have:
#include <iostream>
using namespace std;
int main()
{
int b = 1;
int c = 2;
string a = "(b + c)";
cout << (4 * a) << "\n";
return 0;
}
Is it possible to have string a interpreted literally as if the code had said cout << (4 * (b + c)) << "\n";?
No. C++ is not (designed to be) an interpreted language.
Although it's theoretically possible to override operators for different types, it's very non-recommended to override operators that don't involve your own types. Defining an operator overload for std::string from the standard library may break in future. It's just a bad idea.
But, let's say you used a custom type. You could write a program that interprets the text string as a arithmetic expression. The core of such program would be a parser. It would be certainly possible, but the standard library doesn't provide such parser for you.
Furthermore, such parser wouldn't be able to make connection between the "b" in the text, and the variable b. At the point when the program is running, it has no knowledge of variable names that had been used to compile the program. You would have to specify such information using some form of data structure.
P.S. You forgot to include the header that defines std::string.
#include<string>
///...
auto a=std::to_string(b+c);
std::cout<<4*std::stoi(a)<<std::endl;
You can just use std::string and std::stoi.

Why cout statement is not executing in passing pointer to function?

The cout statement in function call swap is not executing. Why?
#include <iostream>
using namespace std;
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
cout << "Value Swapped" << endl;
}
int main() {
int x = 400, y = 100;
swap(x, y);
cout << "x = " << x << " y = " << y << endl;
return 0;
}
I have expected below output:
Value Swapped
x = 100 y = 400
But the output I have got is:
x = 100 y = 400
You're not seeing "Value swapped" because your swap function never gets called. Instead, you're calling std::swap<int>.
If you hadn't said using namespace std;, you'd have found out that your swap function is being passed integers, but was expecting pointers. Reason #1 not to use using namespace std; -- you can easily end up not calling what you think you are. :)
your function swap is expecting pointers as arguments, but you are passing integers. So instead of calling your function, it's calling the c++ swap function. To better understand this, change the function name 'swap' to any other name like 'swapp' and you'll see this error:
invalid conversion from int to int*
write swap(&x, &y) and you'll get your desired output
Consider choosing a unique enough identifier name such that there will not be a conflict with a namespace identifier (as in std::swap). If you can't choose the name of your identifier, put it inside of a namespace.
Secondly, if the compiler does not enforce the function declaration that you state, you should manually check to see that you passed the variables correctly (i.e., &x and &y instead of x and y).
using namespace std imports another equally named function from namespace std into global namespace, so you end up in having two overloads:
swap(int&, int&); // from std; actually a template instantiation
swap(int*, int*);
You call swap as
swap(x, y);
Now consider: Which are the types of x and y, are they pointers? So decide yourself, which overload will get called?
If you hadn't imported the second overload via using namespace std, which generally is considered bad practice anyway (well, you got a victim of the pitfalls of right away...), you would have ended up in a compilation error instead (integers aren't converted to pointers implicitly!).
To get your function called, you need to make pointers from:
swap(&x, &y);
// ^ ^
Actually, that would have worked even with the imported namespace (despite of being bad practice), as the imported overload is a template, yours an ordinary function, thus yours is considered the more specialised overload and thus will be preferred.

Inbuilt __gcd(A,B) function in C++

recently I get to know about a special function in c++ : __gcd(A,B). this will return the greatest common divisor of A and B.
#include<iostream>
#include<algorithm>
using namespace std;
main()
{
cout<<__gcd(10,40); //op: 10
}
is there any special reason for starting function definition with 2 underscores?
It could be as simple as gcd(A,B) like other STL functions.
Names starting with two underscores are reserved for the implementation, which means that you are not allowed to define such names in your code, and there are no standard guarantees what those names mean if they do exist. However, a vendor might choose to document some such names, in which case you can use them with the product for which the vendor documents them.
In C++17 there are standard library functions for GCD and LCM.
#include <iostream>
#include <numeric>
int main ()
{
int a, b;
std::cin >> a >> b;
std::cout << std::gcd(a,b) << '\n';
return (0);
}

Template class in c++?

I am using a template class to set the data type for a swap function. In the code if i initialize the function name as lower case letter it throws an error
call of overloaded 'swap(double&, double&) is ambiguous
but when i initialize the function name as upper case it works fine.
Will appreciate if someone could explain me why this is happening. Here is my code
#include<iostream>
using namespace std;
template <class T>
void swap(T &a,T &b)
{
T temp;
temp = a;
a = b;
b = temp;
}
int main()
{
double value1 = 2.44;
double value2 = 6.66;
cout<<"\tBefore swap \n";
cout<<"Value 1 = "<< value1 <<"\tValue 2 = " << value2 <<"\n";
swap(value1,value2);
cout<<"\tafter swap \n";
cout<<"Value 1 = "<< value1 <<"\tValue 2 = "<<value2;
}
Instead of
swap(value1,value2);
use
::swap(value1,value2);
This would solve the namespace and ambiguity issue.
because there is already a standard library function std::swap http://www.cplusplus.com/reference/algorithm/swap/ so possibly your compiler does not like it? You pull that in via using namespace std;
Change the name of your swap function because std::swap already exists.
Or you could put it in a separate namespace and use the scope resolution operator, "::", to distinguish yours from the standard one.
This is what happens when you use namespace std;. You may want to be more specific and use:
using std::cout;
using std::endl;
using std::cin;
Already standard library function is defined with templates 'swap' Instead of 'SWAP',It is actually under the std namespace, but because you have a using namespace std line, it exists without the std:: prefix.
As you can see, using the using namespace std isn't always a good option because of possible name collisions, as in this example. In general one should prefer not to use the using directive unless there's a real reason for this - namespaces exist for a reason - to prevent name collisions.

Why does this program swap the values?

I have the following code:
#include "stdafx.h"
#include <iostream>
using namespace std;
#include <conio.h>
#include <cstring>
#include <iomanip>
void swap(long a, long b)
{
long temp;
temp=a;
a=b;
b=temp;
}
int _tmain(int argc, _TCHAR* argv[])
{
int x = 5, y = 3;
cout << x ;
cout << y << endl;
swap(x, y);
cout << x ;
cout << y << endl;
getch();
return 0;
}
The program gives the output:
5 3
3 5
The program actually swaps the values! Why is that? The parameters of the swap() are not pointers or references.
(I am using VS 2005)
Your swap function isn't being called at all.
One of the Standard Library includes that you have included is pulling in <utility>, which declares a function template named swap in the std namespace. Since you are using namespace std;, that swap function is being brought into the global namespace and it is called instead.
Why is std::swap chosen instead of your swap function? Your swap function takes two longs by value; to call that function, an integer promotion is required for each of the int arguments.
std::swap is a function template. It takes two references to T, and when that function template is instantiated with T = int, both arguments are an exact match. So, std::swap is a better match than your function and it is therefore selected during overload resolution.
This is one reason that using namespace std; is evil and should be avoided. If you remove the using directive, your function will be the only function available and it will be called.
Say long instead of int.
Your current code already has a better match for swap, so it avoids the implicit conversion to long, and instead uses the built-in swap from the STL.
On a side note, this ambiguity is somewhat solved using overload sets (also here) in the language D.