Имеет ли оператор унарного + практическое применение?
Был ли унарный оператор +
включен только для симметрии с унарным оператором -
или он нашел практическое применение в коде С++?
Поиск здесь, я наткнулся на Какова цель унарного оператора "+" в C?, но единственные полезные сценарии там включают макросы препроцессора. Это хорошо знать, но они кажутся менее распространенными ситуациями и включают макросы. Существуют ли какие-либо варианты использования более распространенного кода на С++?
Ответы
Ответ 1
char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';
Первая вставка записывает символ a
в cout
. Вторая вставка записывает числовое значение ch
в cout
. Но это немного неясное; он полагается на компилятор, применяющий интегральные акции для оператора +
.
Ответ 2
Симметрия с унарным -
не совсем бесполезна; его можно использовать для акцента:
const int foo = -1;
const int bar = +1;
И перегруженный унарный +
может использоваться для обозначения операции, которая дает то же логическое значение, что и его операнд, при выполнении некоторых нетривиальных вычислений. (Я видел, что это сделано для преобразований типов в Ada, что позволяет унарные +
, но не преобразования) перегружаться.) У меня нет хорошего примера на С++, и можно утверждать, что он будет плохим стиль. (Опять же, я видел много заявлений о перегрузке <<
.)
Что касается того, почему С++ имеет его, он, вероятно, в основном для согласованности с C, который добавил его в стандарт ANSI 1989 года. Обоснование C > просто говорит:
Унарный плюс был принят Комитетом C89 из нескольких реализаций, для симметрии с унарным минусом.
Ответ 3
Если вы явно избегаете семантики значений чисел для класса, любая перегрузка оператора ясна, чтобы не "делать так, как это делают int". В этом случае унарный плюс может иметь какое-либо значение, делая гораздо больше, чем просто возврат *this
Известный пример: Boost.Spirit унарный плюс для встроенного EBNF Kleene Plus создает правило парсера, которое позволяет его аргумент (правило парсера также) совпадать один или несколько раз.
Ответ 4
Унарный оператор +
превращает значение l в значение r:
struct A {
static const int value = 1;
};
// ...
int x = std::min(0, A::value);
Ой! Этот код не будет связываться, потому что кто-то забыл определить (а также объявить) A::value
. std::min
принимает свои аргументы по ссылке, поэтому A::value
должен иметь адрес, с которым ссылка может привязываться к нему (технически одно правило определения говорит, что оно должно быть определено ровно один раз в программе.)
Nevermind, унарный плюс на помощь:
int x = std::min(0, +A::value);
Унарный плюс создает временное значение с тем же значением, а ссылка привязывается к временному, поэтому мы можем обойти отсутствующее определение.
Это не то, что вам нужно часто, но это практическое использование унарного оператора plus.
Ответ 5
Unary + применяет интегральные акции. Ответ @PeteBecker показывает один способ, который может быть полезен.
Для другого, обратите внимание, что тип нумерации с незаданной областью повышается до целочисленного типа, который может представлять все значения в enum
. Поэтому в С++ 03, даже без С++ 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 );
}
Ответ 6
Немного поздно, но здесь очень искривленное использование, которое я наткнулся. По-видимому, оператор +
может быть полезен (если не строго необходим) при разработке защитных мер вокруг возможности столкновения пустых токенов препроцессора. См. этот пост для более углубленного обсуждения.
Это практично, но отнюдь не приятно.