Jaki jest cel jednoargumentowego „+” przed wywołaniem elementów członkowskich std :: numeric_limits <unsigned char>?

130

Widziałem ten przykład w dokumentacji cppreference dlastd::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';
}

Nie rozumiem operatora „+” w

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

Przetestowałem to, zamieniłem na „-” i to też zadziałało. Jaki jest pożytek z takiego operatora „+”?

Zhang
źródło
3
Spróbuj. Co otrzymasz, jeśli pominiesz +?
Pete Becker
4
To pytanie nie wymagałoby zadawania pytań, jeśli
autorowi
jeśli zamienisz -na, wyjścia nie będą miały prawidłowych wartości dla limitów
phuclv
1
Dla przypomnienia, jeśli chcesz wygooglować tego typu rzeczy w sobie, nazywa się to operatorem „jednoargumentowy plus” - jest jednoargumentowy, ponieważ przyjmuje jedną wartość (w tym przypadku rzecz znajdującą się bezpośrednio po niej) i „plus ”to sposób, w jaki można powiedzieć to w sposób przyjazny dla Google +. W takim przypadku Twoje zapytanie będzie prawdopodobnie brzmiało „c ++ jednoargumentowy plus”. To ... nie jest do końca intuicyjne i nadal musisz nauczyć się czytać dokumentację, którą znajdziesz, ale IMO to przydatna umiejętność do kultywowania.
Załóż pozew Moniki

Odpowiedzi:

137

Operator wyjściowy <<po przekazaniu a char(ze znakiem lub bez znaku) zapisze go jako znak .

Te funkcje będą zwracać wartości typu unsigned char. Jak wspomniano powyżej, wypisze znaki, które te wartości reprezentują w bieżącym kodowaniu, a nie ich wartości całkowite.

W +przekształca operatorskiego unsigned charzwrócone w tych funkcji na intpoprzez promowanie całkowitej . Co oznacza, że ​​zamiast tego zostaną wydrukowane wartości całkowite.

Wyrażenie takie jak +std::numeric_limits<unsigned char>::lowest()jest zasadniczo równe static_cast<int>(std::numeric_limits<unsigned char>::lowest()).

Jakiś koleś programista
źródło
37

+jest po to, aby zmienić unsigned charw int. +Operator jest wartość zachowania, ale ma wpływ na indukowanie dowartościowania swojego argumentu. Ma to na celu upewnienie się, że widzisz wartość liczbową zamiast jakiegoś (pół) losowego znaku, który operator <<zostałby wydrukowany, gdy podano typ znaku.

StoryTeller - Unslander Monica
źródło
18

Wystarczy dodać odniesienie do już udzielonych odpowiedzi. Ze standardowego projektu roboczego CPP N4713 :

8.5.2.1 Operatory jednoargumentowe
...

  1. Argument operandu jednoargumentowego operatora + powinien mieć typ arytmetyczny, wyliczenie bez zakresu lub typ wskaźnika, a wynikiem jest wartość argumentu. Promocja integralna jest wykonywana na operandach całkowych lub wyliczeniowych. Typ wyniku to typ promowanego operandu.

I char, short, int, i longsą integralne typy.

PW
źródło
12

Bez +rezultatu będzie inaczej. Następujące fragmenty kodu wyjściowego a 97zamiasta a

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

Powodem jest to, że różne przeciążenia powodują drukowanie różnych typów danych . Nie ma basic_ostream& operator<<( char value );przeciążenia std::basic_ostreami jest wyjaśnione na końcu strony

Argumenty znaków i ciągów znaków (np. Typu charlub const char*) są obsługiwane przez przeciążenia elementów niebędących członkami programu operator<<. Próba wypisania znaku przy użyciu składni wywołania funkcji składowej (np. std::cout.operator<<('c');) Wywoła jedno z przeciążeń (2-4) i wyprowadzi wartość liczbową . Próba wyprowadzenia ciągu znaków przy użyciu składni wywołania funkcji składowej wywoła funkcję overload (7) i zamiast tego wydrukuje wartość wskaźnika.

Przeciążenie non-member która zostanie wywołana gdy mijamy charzmienna jest

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

która wypisuje znak w punkcie kodowym ch

Więc w zasadzie, jeśli przejdzie char, signed charalbo unsigned charbezpośrednio do strumienia będzie to wydrukować znak na zewnątrz. Jeśli spróbujesz usunąć z +powyższych wierszy, zobaczysz że drukuje jakieś "dziwne" lub niewidoczne znaki, co nie jest tym czego można by się spodziewać

Jeśli chcesz ich wartości liczbowych zamiast należy wywołać przeciążenie na short, int, longlub long long. Najłatwiejszym sposobem jest promowanie od chardo intz jednoargumentowym plusem +. To jeden z tych rzadkich przydatnych aplikacji na jednoargumentowego operatora powiększonej . intBędzie również działać wyraźna obsada do

Jest wielu ludzi, którzy napotkali ten problem na SO

phuclv
źródło
1
Czy chodziło Ci o jednoargumentowy plus , a nie minus?
Ruslan,