Какова цель унарного "+" перед вызовом членов std :: numeric_limits <unsigned char>? - PullRequest
0 голосов
/ 03 сентября 2018

Я видел этот пример в документации cppreference для 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';
}

Я не понимаю оператора "+" в

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

Я проверил его, заменил на "-", и это тоже сработало. Какая польза от такого оператора "+"?

Ответы [ 4 ]

0 голосов
/ 03 сентября 2018

Без + результат будет другим. Следующий фрагмент кода выводит a 97 вместо a a

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

Причина в том, что из-за разных перегрузок печатает данные разных типов . Для std::basic_ostream перегрузки basic_ostream& operator<<( char value ); нет, и это объясняется в конце страницы

Символьные и символьные строковые аргументы (например, типа char или const char*) обрабатываются не членскими перегрузками из operator<<. Попытка вывести символ с использованием синтаксиса вызова функции-члена (например, std::cout.operator<<('c');) вызовет одну из перегрузок (2-4) и выведет числовое значение . Попытка вывести символьную строку с использованием синтаксиса вызова функции-члена вызовет перегрузку (7) и вместо этого выведет значение указателя.

Перегрузка , не являющаяся членом , которая будет вызываться при передаче переменной char, равна

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

, который печатает символ в кодовой точке ch

Таким образом, если вы передадите char, signed char или unsigned char непосредственно в поток, он выведет символ. Если вы попытаетесь удалить + в приведенных выше строках, вы увидите, что он печатает некоторые «странные» или невидимые символы, что не соответствует ожиданиям

Если вы хотите вместо этого использовать их числовые значения, вы должны вызвать перегрузку для short, int, long или long long. Самый простой способ сделать это - повысить с char до int с унарным плюсом +. Это одно из редких полезных приложений унарный оператор плюс . Явное приведение к int также будет работать

Есть много людей, которые сталкивались с такой проблемой на SO, как

0 голосов
/ 03 сентября 2018

Оператор вывода << при передаче char (со знаком или без знака) запишет его как символ .

Эти функции будут возвращать значения типа unsigned char. И, как отмечалось выше, будут печататься символы, которые эти значения представляют в текущей кодировке, а не их целочисленные значения.

Оператор + преобразует unsigned char, возвращаемый этими функциями, в целочисленное продвижение int до . Это означает, что вместо этого будут напечатаны целочисленные значения.

Выражение типа +std::numeric_limits<unsigned char>::lowest() по существу равно static_cast<int>(std::numeric_limits<unsigned char>::lowest()).

0 голосов
/ 03 сентября 2018

Просто чтобы добавить ссылку на уже даные ответы. Из стандартного рабочего проекта CPP N4713 :

8.5.2.1 Унарные операторы
...

  1. Операнд унарного оператора + должен иметь арифметическое, перечисление с незаданной областью или тип указателя, а результатом является значение аргумента. Интегральное продвижение выполняется для целочисленных операндов или операндов перечисления. Тип результата - это тип повышенного операнда.

И char, short, int и long являются целочисленными типами.

0 голосов
/ 03 сентября 2018

+ здесь, чтобы превратить unsigned char в int. Оператор + сохраняет значение, но он вызывает интегральное продвижение своего операнда. Нужно убедиться, что вы видите числовое значение вместо некоторого (полу) случайного символа, который operator << будет печатать при заданном типе символа.

...