-1

considering following code:

#include <iostream>
using namespace std;

template <typename T>

T foo(T a, T b) {
    if (a<b) {
        return b;
    }
    return a;
}

int main() {
    cout <<foo<int>(3,4) <<endl;
    cout <<foo(1,2) <<endl;
    cout <<foo("hello","goodbuy") <<endl; //>>>>>this line <<<<<<
    cout <<foo<float>(3,4) <<endl;    
}

it prints out: 4 2 hello 4 but when i changed the marked line with this: cout <('hello','goodbuy') <

warning: character constant too long for its type
     cout <<foo<int>('hello','goodbuy') <<endl; 
                     ^
warning: character constant too long for its type
     cout <<foo<int>('hello','goodbuy') <<endl; 
                         ^

and prints out : 4 2 1701604463 4 why does it print out that big number? some help or guidance please thank you

Pamador
  • 158
  • 2
  • 8
  • 5
    Use `"` for strings and `'` for individual characters. – Brian Bi Jun 14 '14 at 00:30
  • Dupe? I'll let the masses decide. http://stackoverflow.com/questions/3960954/c-multicharacter-literal – Drew Dormann Jun 14 '14 at 00:40
  • That's a function template, not a template function. – chris Jun 14 '14 at 00:58
  • possible duplicate of [What do single quotes do in C++ when used on multiple characters?](http://stackoverflow.com/questions/7459939/what-do-single-quotes-do-in-c-when-used-on-multiple-characters) – Csq Jun 14 '14 at 07:41

2 Answers2

2

Main problem:

'hello'

is a character literal that denotes an integer, if it is at all accepted (how many characters you can use depends on the compiler). At one time it was used to generate magic numbers that e.g. denoted file types. For example, in old DOS a file that started with the characters MZ was an executable, and the Windows command interpreter, although not Windows Explorer, still recognizes that silly magic:

[H:\dev\test\0119]
> echo MZ >blah.txt

[H:\dev\test\0119]
> blah.txt
This version of H:\dev\test\0119\blah.txt is not compatible with the version of Windows you're running. Check your computer's system informa
tion and then contact the software publisher.

[H:\dev\test\0119]
> _

In old C code that number would perhaps be denoted by an integer constant like 'ZM'.


Now, starting with your definition …

template< typename T >
T foo(T a, T b) {
    if (a<b) {
        return b;
    }
    return a;
}

Let me first rewrite it to a form I’m more comfortable with:

template< class Type >
auto foo( Type const a, Type const b)
    -> Type
{ return (a<b? b : a); }

I do this rewrite up front so that that aspect can be ignored in the following.

Regardless of form it has a problem when the actual arguments are of different types, e.g. in the call foo( 3, 4.5 ). Then argument type deduction will fail, so that the type must be specified explicitly, foo<double>( 3, 4.5 ). How to avoid that?

For numeric types you can deal with that like this:

template< class Type1, class Type2 >
auto foo( Type1 const a, Type2 const b )
    -> decltype( a + b )
{ return (a<b? b : a); }

Now you want to call it with string literals as arguments. They will be deduced as type char const*, and then the a + b expression will not compile. For you can't add pointers.

For that matter, the a<b expression would yield an probably unintended result, just comparing the pointer values instead of a lexicographic compare of the strings.

One solution is then to provide an overload of the function:

auto foo( char const* const a, char const* const b)
    -> char const*
{ return (strcmp( a, b ) < 0? b : a); }

Then you can call it like foo( "bravo", "alpha" ).


Disclaimer: all C++ code untouched by compilers’ hands.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • 1
    Another interesting use of multicharacter literals is in Boost's TMP library, where you can build compile-time strings via something like `<'1234', '5678', 'acbd'>`. Of course with C++11, it becomes possible to use a macro to instead do `MAKE_TMP_STRING("12345678abcd")` with no ugly compiler-dependent sorcery (though there is ugly macro sorcery taking its place). – chris Jun 14 '14 at 01:04
  • thanks for the effort but it didn't answer my question or i didn't understand it probably. my questions was that when you have that code exactly with single quote, and , why does it print out that number? ignoring compiler warning, what are the steps that leads to that number? – Pamador Jun 14 '14 at 01:36
  • @Pamador: well, if you don't understand why an integer prints as an integer, then i'm sorry, i tried my best but it wasn't good enough. – Cheers and hth. - Alf Jun 14 '14 at 01:41
  • when i try that like this foo ('hello', 'goodbuy');it prints out y. – Pamador Jun 14 '14 at 01:41
  • Does it help if we examine what `ZM` can mean with one particular compiler? ASCII code for Z is 64 + 26 = 90. ASCII code for M is 64 + 13 = 77. So you have two byte values 90 and 77, or in hex, 5A and 4D. On a PC integers have the least significant part at lowest address if 4D (the M) is the first byte, then in ordinary base 16 notation we have the number 5A4D. Now use e.g. Python (that's what I'm doing) to print out the decimal value. Typing `0x5A4D` at the Python prompt gives 23117. So that's what `'ZM'` means with a PC compiler that lays out the ASCII values in reverse order, with M first. – Cheers and hth. - Alf Jun 14 '14 at 01:50
  • @Cheersandhth.-Alf, ok you mean if i call that function like foo('hello', 'goodbuy') it actually compare their pointers value, and returns unintended result, right?...plus i'm learning. these are new to me. thanks ayway – Pamador Jun 14 '14 at 01:56
  • no, not pointer values. `'hello'` denotes an integer, *if* it is accepted by the compiler. what integer it denotes also depends on the compiler. that is what you're passing, an integer. it prints as an integer because it is an integer. – Cheers and hth. - Alf Jun 14 '14 at 01:57
  • ok, i think i got what you mean, so how that number calculated? every letter has ascii code right, does it relate to that? – Pamador Jun 14 '14 at 02:02
  • uhm, yes, something like that. – Cheers and hth. - Alf Jun 14 '14 at 02:04
  • all s fine now. thanks. i'd really appreciate your response. i want to vote up but i cant...so may universe bless you... – Pamador Jun 14 '14 at 02:06
  • ok, i finally found out why that number...thanks to @Cheersandhth.-Alf...the foo function actually goes up to 'ello' each character has ascii code, if you put all the hex code next to each other you get this 0X656c6c6f which represent 'ello' no 'h' included because of system limit probably. then if you convert that to decimal you get that number 1701604463 – Pamador Jun 14 '14 at 02:38
1

As commented by @Brian, use " for strings. Otherwise you get a multicharacter literal (link1) (link2).

int main() {
    cout << foo("hello","goodbuy") <<endl;
}

This code compiles, but it has a problem! "hello" and "goodbuy" are arrays of characters, that are converted to a pointer to the first letter when passing as a parameter. So in the template functions you will compare two pointers, which is definitely not what you want (because the return value of this comparison is undefined). One solution is to convert the character arrays into an std::string.

#include <string>

int main() {
    cout << foo<string>("hello", "goodbuy") <<endl;
}
Community
  • 1
  • 1
Csq
  • 5,775
  • 6
  • 26
  • 39
  • this is good note, but still i want to know why it prints out the number with single quote? – Pamador Jun 14 '14 at 01:39
  • @Pamador: read the link about the multicharacter literals, there is no point in repeating what is written there. – Csq Jun 14 '14 at 07:38
  • Yet another link: http://stackoverflow.com/questions/7459939/what-do-single-quotes-do-in-c-when-used-on-multiple-characters – Csq Jun 14 '14 at 07:38