What is the purpose of a unary "+" before a call to std::numeric_limits<unsigned char> members?

C++CharUnary Operator

C++ Problem Overview


I saw this example in cppreference's documentation for std::numeric_limits

#include <limits>
#include <iostream>
 
int main() 
{
    std::cout << "type\tlowest()\tmin()\t\tmax()\n\n";
 
    std::cout << "uchar\t"
              << +std::numeric_limits<unsigned char>::lowest() << '\t' << '\t'
              << +std::numeric_limits<unsigned char>::min() << '\t' << '\t'
              << +std::numeric_limits<unsigned char>::max() << '\n';
    std::cout << "int\t"
              << std::numeric_limits<int>::lowest() << '\t'
              << std::numeric_limits<int>::min() << '\t'
              << std::numeric_limits<int>::max() << '\n';
    std::cout << "float\t"
              << std::numeric_limits<float>::lowest() << '\t'
              << std::numeric_limits<float>::min() << '\t'
              << std::numeric_limits<float>::max() << '\n';
    std::cout << "double\t"
              << std::numeric_limits<double>::lowest() << '\t'
              << std::numeric_limits<double>::min() << '\t'
              << std::numeric_limits<double>::max() << '\n';
}

I don't understand the "+" operator in

<< +std::numeric_limits<unsigned char>::lowest()

I have tested it, replaced it with "-", and that also worked. What is the use of such a "+" operator?

C++ Solutions


Solution 1 - C++

The output operator << when being passed a char (signed or unsigned) will write it as a character.

Those function will return values of type unsigned char. And as noted above that will print the characters those values represent in the current encoding, not their integer values.

The + operator converts the unsigned char returned by those functions to an int through integer promotion. Which means the integer values will be printed instead.

An expression like +std::numeric_limits<unsigned char>::lowest() is essentially equal to static_cast<int>(std::numeric_limits<unsigned char>::lowest()).

Solution 2 - C++

+ is there to turn the unsigned char into an int. The + operator is value preserving, but it has the effect of inducing integral promotion on its operand. It's to make sure you see a numerical value instead of some (semi-)random character that operator << would print when given a character type.

Solution 3 - C++

Just to add a reference to the answers already given. From the CPP standard working draft N4713:

> 8.5.2.1 Unary operators
...
>> 7. The operand of the unary + operator shall have arithmetic, unscoped enumeration, or pointer type and the result is the value of the argument. Integral promotion is performed on integral or enumeration operands. The type of the result is the type of the promoted operand.

And char, short, int, and long are integral types.

Solution 4 - C++

Without + the result will be different. The following snippet outputs a 97 instead of a a

char ch = 'a';
std::cout << ch << ' ' << +ch << '\n';

The reason is because different overloads prints different types of data. There's no basic_ostream& operator<<( char value ); overload for std::basic_ostream and it's explained at the end of the page

> Character and character string arguments (e.g., of type char or const char*) are handled by the non-member overloads of operator<<. Attempting to output a character using the member function call syntax (e.g., std::cout.operator<<('c');) will call one of overloads (2-4) and output the numerical value. Attempting to output a character string using the member function call syntax will call overload (7) and print the pointer value instead.

The non-member overload that will be called when you pass a char variable is

template< class CharT, class Traits> basic_ostream<CharT,Traits>& operator<<(
    basic_ostream<CharT,Traits>& os, char ch );

which prints out the character at the codepoint ch

So basically if you pass char, signed char or unsigned char directly to the stream it'll print the character out. If you try removing the + on the above lines you'll see that it prints some "strange" or non-visible characters which is not what one would expect

If you want their numerical values instead you must call the overload for short, int, long or long long. The easiest way to do this is promoting from char to int with unary plus +. That's one of the rare useful applications of the unary plus operator. An explicit cast to int will also work

There are many people who faced that problem on SO like

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionZhangView Question on Stackoverflow
Solution 1 - C++Some programmer dudeView Answer on Stackoverflow
Solution 2 - C++StoryTeller - Unslander MonicaView Answer on Stackoverflow
Solution 3 - C++P.WView Answer on Stackoverflow
Solution 4 - C++phuclvView Answer on Stackoverflow