Overloaded function. Why it's ambiguous here? - c++

I have my function overloaded in code below:
void function(char x, double y) {
cout << "char, double" << endl;
}
void function(int x, int y) {
cout << "int, int" << endl;
}
int main() {
function('a', 'b');
return 0;
}
When i try to compile it says me: "[Warning] ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second"
How does compiler make implicit conversions here so that it's ambiguous which candidate is right?

The literal constants 'a' and 'b' have type char, so there is no exact match. The ambiguity occurs because the first parameter matched the first function, but the preferred conversion of the second is to int, matching the second function.
GCC is very explicit about this, issuing the following diagnostic:
warning: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for the second
GCC seems to be saying, I could resolve this for you, but ISO C++ won't allow it. Type agreement is however important to good code quality and avoidance of errors.
You can coerce the selection by casting:
function( static_cast<int>('a'), static_cast<int>('b') );
or by supplying a function( char, char ) overload.

There are implicit conversions between double, int, and char in C++, so you should use static_cast<int> to convert data from char to int for example.
function( static_cast<int>(c), static_cast<int>(d) );
this will call function( int, int );
In your particular case, you use 'a' and 'b' character literals, which, as I mentioned above, have implicit conversions to int and double, because a char variable represents the ASCII value of the character entered in the assignment operator. Hence, we can initialize an unsigned char variable, or a char in the ways below:
unsigned char a = 97; // the ASCII decimal code for "a"
unsigned char b = 'a'; // translates into 97
Since an unsigned char or char variables is an 8 bits variable, and int is a 32 bit value, they have implicit conversions.

For overload A to be chosen over overload B, the conversions for each argument to A must be as good or better than those for B, and at least one must be better.
In your case, A has (exact match, integral->floating), whereas B has (integral promotion, integral promotion).
Exact match is better than integral promotion, but integral promotion is better than integral->floating conversion. So A has a better conversion in the first argument, and B in the second. So it's ambiguous which one is better overall.

Trying ('a', 'b') for function(char, double) requires no conversion for 'a', and a floating-integral conversion for 'b' (from char to double).
For function(int, int), both 'a' and 'b' require integral promotion (from char to int).

Related

Way of casting in va_arg

I'm doing some research about variadic functions and arguments.
I noticed that va_arg is able to cast objects into other objects. For example, when the next argument is a char, but you are using va_arg like it should be an int, it casts the char to an int:
Function call:
AddNumbers(3, 5, 'a', 20);
Function declaration:
int AddNumbers(int count, ...) {
int result;
va_list va;
va_start(va, count);
for(int i = 0; i < count; ++i) {
result += va_arg(va, int);
}
return result;
}
So my question is: what kind of casting does this function use (C-style, dynamic_cast, etc.)?
It has nothing to do with casting. In this case it works because of argument promotion.
When you use a varargs function, integer types smaller than int (like e.g. char) are promoted to int.
That's why it works when passing character literals to the function. If you try some other type, like e.g. a floating point value, then it will no longer work.
As for what the va_arg macro (it's mostly implemented as a macro) does, it is totally implementation dependent. It might not do any casting at all, but use some other form of type punning instead.
It is not exactly casting, because va_arg is a macro, not a function. So the type of va_arg(va, int) is by construction int.
But promotions do occur when calling the variadic function (except for the argument preceding the ellipsis.
So in AddNumbers(3, 5, 'a', 20);, the character 'a' is promoted to an int. You can then either use it as an int as your code does, or convert it back to a char (a conversion not a cast) which is defined because the int value can be represented as a char (by construction)
If I understand your question correctly:
C performs certain "casts" by default when calling a variadic function. GCC calls these default argument promotions. They are:
Signed or unsigned char and short int become signed or unsigned int.
float becomes double.
This isn't really a matter of va_arg doing a cast within AddNumbers; instead, when calling AddNumbers, the caller promotes the arguments to AddNumbers as part of pushing them onto the stack for AddNumbers to use.

What are some reasons you cast a char to an int in C++?

What are some reasons you would cast a char to an int in C++?
It rarely makes sense to cast a char value to int.
First, a bit of terminology. A cast is an explicit conversion, specified via a cast operator, either the C-style (type)expr or one of the C++ casts such as static_cast<type>(expr). An implicit conversion is not a cast. You'll sometimes see the phrase "implicit cast", but there is no such thing in C++ (or C).
Most arithmetic operators promote their operands if they're of an integer type narrower than int or unsigned int. For example, in the expression '0' + 1, the char value of 0 is promoted to int before the addition, and the result is of type int.
If you want to assign a char value to an int object, just assign it. The value is implicitly converted, just as it would be if you used a cast.
In most cases, implicit conversions are preferred to casts, partly because they're less error-prone. An implicit conversion specified by the language rules usually does the right thing.
There are cases where you really do need to cast a char to int. Here's one:
char c = 'A';
std::cout << "c = '" << c << "' = " << static_cast<int>(c) << "\n";
The overloaded << operator accepts either char or int (among many other types), so there's no implicit conversion. Without the cast, the same char value would be used twice. The output (assuming an ASCII-based character set) is:
c = 'A' = 65
This is an unusual case because the << operator treats types char and int very differently. In most contexts, since char is already an integer type, it doesn't really matter whether you use a char or int value.
I can think of one other very obscure possibility. char values are almost always promoted to int. But for an implementation in which plain char is unsigned and char and int are the same width, plain char is promoted to unsigned int. This can only happen if CHAR_BIT >= 16 and sizeof (int) == 1. You're very unlikely to encounter such an implementation. Even on such a system, it usually won't matter whether char is promoted to int or to unsigned int, since either promotion will yield the correct numeric value.
In general, this should rarely ever happen as it's fairly explicit when to use a char and when to use an int.
However if you were interested in performing arithmetic on a group of chars, you would require more memory to store the overall value, for this reason you could would usually use an int(or any other data type) to store the overall value.
By doing so you would more then likely implicitly cast the chars to the chosen data type.
However you can also explicitly cast these chars before or during calculation(Later versions of C++ take care of this for you though).
This is one such and more common use for the casting of chars.
However in practice, this can usually be avoided as it makers for stronger cleaner code in the long run

How does C treat char sums?

When I'm in C++, and I call an overloaded function foo, like so:
foo('e' - (char) 5)
it can output "this is a char" or "this is an int" based on the type result. I get "this is an int" from my program, like this:
#include <iostream>
void foo(char x)
{
std::cout << "output is a char" << std::endl;
}
void foo(int x)
{
std::cout << "output is an int" << std::endl;
}
int main()
{
foo('a' + (char) 5);
}
My instructor says that in C, the expression above, ('a' + (char) 5), evaluates as a char. I see in the C99 standard that chars are promoted to ints to find the sum, but does C recast them back to chars when it's done? I can't find any references that seem credible saying one way or another what C actually does after the promotion is completed, and the sum is found.
Is the sum left as an int, or given as a char? How can I prove this in C, or is there a reference I'm not understanding/finding?
From the C Standard, 6.3.1.8 Usual arithmetic conversions, emphasis mine:
Many operators that expect operands of arithmetic type cause conversions and yield result
types in a similar way. The purpose is to determine a common real type for the operands
and result. For the specified operands, each operand is converted, without change of type
domain, to a type whose corresponding real type is the common real type. Unless
explicitly stated otherwise, the common real type is also the corresponding real type of
the result, whose type domain is the type domain of the operands if they are the same,
and complex otherwise. This pattern is called the usual arithmetic conversions:
First, if the correspeonding real type of either operand is long double...
Otherwise, if the corresponding real type of either operand is double...
Otherwise, if the corresponding real type of either operand is float...
Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:
If both operands have the same type, then no further conversion is needed.
So you are exactly correct. The type of the expression 'a' + (char) 5 is int. There is no recasting back to char, unless explicitly asked for by the user. Note that 'a' here has type int, so it's only the (char)5 that needs to be promoted. This is stipulated in 6.4.4.4 Character Constants:
An integer character constant is a sequence of one or more multibyte characters enclosed
in single-quotes, as in 'x'.
...
An integer character constant has type int.
There is an example demonstrating the explicit recasting to char:
In executing the fragment
char c1, c2;
/* ... */
c1 = c1 + c2
the ‘‘integer promotions’’ require that the abstract machine promote the value of each variable to int size and then add the two ints and truncate the sum. Provided the addition of two chars can be done without overflow, or with overflow wrapping silently to produce the correct result, the actual execution need only produce the same result, possibly omitting the promotions.
The truncation here only happens because we assign back to a char.
No, C does not recast them back to chars.
The standard (ISO/IEC 9899:1999) says (6.3.1.8 Usual arithmetic conversions):
Many operators that expect operands of arithmetic type cause conversions and yield result
types in a similar way. The purpose is to determine a common real type for the operands
and result. For the specified operands, each operand is converted, without change of type
domain, to a type whose corresponding real type is the common real type. Unless
explicitly stated otherwise, the common real type is also the corresponding real type of
the result, whose type domain is determined by the operator.
Your instructor seems to be wrong. Additional to your standard find that the arithmetic promotes to int, we can use a simple test program to show the behavior (no standard prove of course, but the same level of proof as your C++ test):
#include <stdio.h>
int main () {
printf("%g",'c' - (char)5);
}
produces
Warning: format specifies type 'double' but argument has type 'int'
with gcc and clang.
You can't determine the type of an expression as easily in C, but you can easily determine the size of an expression:
#include <stdio.h>
int main(void) {
printf("sizeof(char)==1\n");
printf("sizeof(int)==%u\n", sizeof(int));
printf("sizeof('a' + (char) 5)==%u\n", sizeof('a' + (char) 5));
return 0;
}
This gives me:
sizeof(char)==1
sizeof(int)==4
sizeof('a' + (char) 5)==4
which at least proves that 'a' + (char) 5 is not of type char.
It's promoted to an int, and there's nothing to tell the compiler it should use anything else. You can convert back to a char like this:
foo((char)('a' + 5));
This tells the compiler to treat the result of the calculation as a char, otherwise it leaves it as an int.
Section 6.5.2.2/6
If the expression that denotes the called function has a type that
does not include a prototype, the integer promotions are performed on
each argument...
So the answer to your question depends on the function prototype. If the function is declared as
void foo(int x)
or
void foo()
then the function argument will be passed as an int.
OTOH, if the function is declared as
void foo( char x )
then the result of the expression will be implicitly cast to char.
In C (unlike C++), the character literal 'a' has type int (§6.4.4.4¶10: "An integer character constant has type int.")
Even if that were not the case, the C standard clearly states that prior to the evaluation of the operator +, "[i]f both operands have arithmetic type, the usual arithmetic conversions are performed on them." (C11, §6.5.6 ¶4) In this respect, C and C++ have identical semantics. (See [expr.add] §5.7¶1 of C++)
From the C++ Standard (C++ Working Draft N3797, 5.7 Additive operators)
1 The additive operators + and - group left-to-right. The usual
arithmetic conversions are performed for operands of arithmetic or
enumeration type.
and (5 Expressions)
10 Many binary operators that expect operands of arithmetic or
enumeration type cause conversions and yield result types in a similar
way. The purpose is to yield a common type, which is also the type of
the result. This pattern is called the usual arithmetic conversions,
which are defined as follows:
...
— Otherwise, the integral promotions (4.5) shall be performed on
both operands.62 Then the following rules shall be applied to the
promoted operands:
Thus the expression in the function call
foo('a' + (char) 5);
has type int.
To call the overloaded function with parameter of type char you have to write for example
foo( char( 'a' + 5 ) );
or
foo( ( char )( 'a' + 5 ) );
or you can use C++ casting like
foo( static_cast<char>( 'a' + 5 ) );
The above quotes from the C++ Standard also are valid for C Standard. The visible difference is that in C++ character literals have type char while in C they have type int.
So in C++ the output of the statement
std::cout << sizeof( 'a' ) << std::endl;
will be equal to 1.
While in C the output of the statement
printf( "%zu\n", sizeof( 'a' ) );
will be equal to sizeof( int ) that is usually equal to 4.

Can I pass a char where an integer is expected in printf?

Is the following code correct?
char mychar = 200;
printf("%x", mychar);
According to http://www.cplusplus.com/reference/clibrary/cstdio/printf/ %x expects an integer (4 bytes with my compiler) and I only pass 1 byte here. Since printf makes use of varargs, my fear is that this only works because of byte alignment on the stack (i.e. a char always uses 4 bytes when pushed on the stack).
I think it would be better to write:
char mychar = 200;
printf("%x", static_cast<int>(mychar));
Do you think the first code is safe anyway? If not, do you think I could get a different output if I switch to a bigendian architecture?
In your example, the argument is actually of type int. mychar is promoted to int due to the default argument promotions.
(C99, 6.5.2.2p6) "If the expression that denotes the called function has a type that does not include a prototype, the integer promotions are performed on each argument, and arguments that have type float are promoted to double. These are called the default argument promotions."
and (emphasis mine):
(C99, 6.5.2.2p7) "If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type. The ellipsis notation in a function prototype declarator causes argument type conversion to stop after the last declared parameter. The default argument
promotions are performed on trailing arguments."
Note that technically the x conversion specifier requires an unsigned int argument but int and unsigned int types are guaranteed to have the same representation.
This only works for you because your platform is able to interpret an int (to which your char is promoted) as an unsigned, this is what %x expects. To be sure that this always works you should use and appropriate format specifier, namely %d.
Since it seems that you want to use char as numerical quantity it would be better to use the two alternative types signed char or unsigned char to make your intention clear. char can be a signed or unsigned type on function of your platform. The correct specifier for unsigned char would then be %hhx.
Simply use printf("%hhx", mychar). And please, don't use cplusplus.com as a reference. This question only proves its reputation of containing many errors and leaving out a lot of information.
If you're using C++, then you might want to use streams instead.
You will need to cast characters to integers, otherwise they will be printed as glyphs. Also, signed characters will be sign extended during the cast, so it's better to use unsigned char. For example a char holding 0xFF will print as 0xFFFFFFFF unless casted to unsigned char first.
#include <iostream>
#include <iomanip>
int main(void){
char c = 0xFF;
std::cout << std::hex << std::setw(2) << std::setfill('0');
std::cout << static_cast<int>(static_cast<unsigned char>(c)) << std::endl;
return 0;
}

Type Conversion/Casting Confusion in C++

What is Type Conversion and what is Type Casting?
When should I use each of them?
Detail: Sorry if this is an obvious question; I'm new to C++, coming from a ruby background and being used to to_s and to_i and the like.
Conversion is when a value is, um, converted to a different type. The result is a value of the target type, and there are rules for what output value results from what input (of the source type).
For example:
int i = 3;
unsigned int j;
j = i; // the value of "i" is converted to "unsigned int".
The result is the unsigned int value that is equal to i modulo UINT_MAX+1, and this rule is part of the language. So, in this case the value (in English) is still "3", but it's an unsigned int value of 3, which is subtly different from a signed int value of 3.
Note that conversion happened automatically, we just used a signed int value in a position where an unsigned int value is required, and the language defines what that means without us actually saying that we're converting. That's called an "implicit conversion".
"Casting" is an explicit conversion.
For example:
unsigned int k = (unsigned int)i;
long l = long(i);
unsigned int m = static_cast<unsigned int>(i);
are all casts. Specifically, according to 5.4/2 of the standard, k uses a cast-expression, and according to 5.2.3/1, l uses an equivalent thing (except that I've used a different type). m uses a "type conversion operator" (static_cast), but other parts of the standard refer to those as "casts" too.
User-defined types can define "conversion functions" which provide specific rules for converting your type to another type, and single-arg constructors are used in conversions too:
struct Foo {
int a;
Foo(int b) : a(b) {} // single-arg constructor
Foo(int b, int c) : a(b+c) {} // two-arg constructor
operator float () { return float(a); } // conversion function
};
Foo f(3,4); // two-arg constructor
f = static_cast<Foo>(4); // conversion: single-arg constructor is called
float g = f; // conversion: conversion function is called
Classic casting (something like (Bar)foo in C, used in C++ with reinterpret_cast<>) is when the actual memory contents of a variable are assumed to be a variable of a different type. Type conversion (ie. Boost's lexical_cast<> or other user-defined functions which convert types) is when some logic is performed to actually convert a variable from one type to another, like integer to a string, where some code runs to logically form a string out of a given integer.
There is also static and dynamic casting, which are used in inheritance, for instance, to force usage of a parent's member functions on a child's type (dynamic_cast<>), or vice-versa (static_cast<>). Static casting also allows you to perform the typical "implicit" type conversion that occurs when you do something like:
float f = 3.14;
int i = f; //float converted to int by dropping the fraction
which can be rewritten as:
float f = 3.14;
int i = static_cast<int>(f); //same thing
In C++, any expression has a type. when you use an expression of one type (say type S) in a context where a value of another type is required (say type D), the compiler tries to convert the expression from type S to type D. If such an implicit conversion doesn't exist, this results in an error. The word type cast is not standard but is the same as conversion.
E.G.
void f(int x){}
char c;
f(c); //c is converted from char to int.
The conversions are ranked and you can google for promotions vs. conversions for more details.
There are 5 explicit cast operators in C++ static_cast, const_cast, reinterpret_cast and dynamic_cast, and also the C-style cast
Type conversion is when you actually convert a type in another type, for example a string into an integer and vice-versa, a type casting is when the actual content of the memory isn't changed, but the compiler interpret it in a different way.
Type casting indicates you are treating a block of memory differently.
int i = 10;
int* ip = &i;
char* cp = reinterpret_cast<char*>(ip);
if ( *cp == 10 ) // Here, you are treating memory that was declared
{ // as int to be char.
}
Type conversion indicates that you are converting a value from one type to another.
char c = 'A';
int i = c; // This coverts a char to an int.
// Memory used for c is independent of memory
// used for i.