Имеет ли оператор unary + практическое применение?

был унарный + оператора включен только для симметрии с унарным - оператор, или он находит практическое применение в коде C++?

поиск здесь, я наткнулся на какова цель унарного оператора ' + ' в C?, но единственные полезные сценарии там включают макросы препроцессора. Это хорошо известно, но они кажутся менее распространенными ситуациями и включают макросы. Существуют ли какие-либо варианты использования с более распространенным кодом C++?

6 ответов


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

первая вставка записывает символ a to cout. Вторая вставка записывает числовое значение ch to cout. Но это немного неясно; он полагается на компилятор, применяющий интегральные рекламные акции для + оператора.


симметрии с унарным - не совсем бесполезно; его можно использовать для акцента:

const int foo = -1;
const int bar = +1;

и перегружен унарный + может использоваться для обозначения операции, которая дает то же самое логическое значение как его операнд при выполнении некоторых нетривиальных вычислений. (Я видел, как это делается для преобразования типов в Ada, что позволяет unary +, но не преобразования, которые будут перегружены.) У меня нет хорошего примера C++, и можно поспорить что это будет некрасиво. (Опять же, я видел много разглагольствований о перегрузке <<.)

по состоянию на почему C++ имеет его, вероятно, в основном для согласованности с C, который добавил его со стандартом ANSI 1989 года. The C Обоснование просто говорит:

унарный плюс был принят Комитетом C89 из нескольких реализации, для симметрии с унарным минусом.


Если вы явно остаетесь в стороне от любой семантики числового значения для класса,любой перегрузка оператора понятна, чтобы не "делать так, как делают ints". В этом случае унарный плюс может получить любой смысл, делая гораздо больше, чем просто возвращение *this

яркий пример: импульс.Дух унарный плюс для встроенного EBNF в Kleene Plus генерирует правило парсера, которое позволяет его аргументу (правило парсера также) совпадать один или несколько раз.


унарный + оператор превращает значение lvalue в значение rvalue:

struct A {
  static const int value = 1;
};

// ...

int x = std::min(0, A::value);

Ах нет! Этот код не будет связан, потому что кто-то забыл определить (а также объявить) A::value. std::min принимает свои аргументы по ссылке so A::value должен иметь адрес, чтобы ссылка могла привязываться к нему (технически, правило одного определения говорит, что оно должно быть определено точно один раз в программе.)

неважно, унарный плюс на помощь:

int x = std::min(0, +A::value);

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

это не то, что вам нужно часто, но это практическое использование унарного оператора plus.


Unary + применяет интегральные акции. Ответ @PeteBecker показывает один из способов, который может быть полезен.

для другого обратите внимание, что тип перечисления без области повышается до целочисленного типа, который может представлять все значения в enum. Так что в C++03, даже без c++11 std::underlying_type<T>, вы могли бы сделать:

enum MyBitMask {
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4,
    Flag4 = 0x8000000
};

inline MyBitMask operator&(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x & +y );
}

inline MyBitMask operator|(MyBitMask x, MyBitMask y) {
    return static_cast<MyBitMask>( +x | +y );
}

немного поздно, но вот очень закрученный, я наткнулся на. Видимо + оператор может быть полезен (если, возможно, не строго необходим) при разработке гарантий вокруг возможности столкнуться с пустыми токенами препроцессора. См.этот пост для более углубленного обсуждения.

это практично, но отнюдь не приятное.