単項演算子は、単項演算+
子との対称性のためにのみ含まれていました-
か、それともC ++コードで実用的ですか?
ここを検索して、Cの単項'+'演算子の目的は何ですか?、しかし、そこにある唯一の有用なシナリオは、プリプロセッサマクロを含みます。それらは知っておくとよいですが、あまり一般的ではない状況のようで、マクロが関係しています。より一般的なC++コードを含むユースケースはありますか?
単項演算子は、単項演算+
子との対称性のためにのみ含まれていました-
か、それともC ++コードで実用的ですか?
ここを検索して、Cの単項'+'演算子の目的は何ですか?、しかし、そこにある唯一の有用なシナリオは、プリプロセッサマクロを含みます。それらは知っておくとよいですが、あまり一般的ではない状況のようで、マクロが関係しています。より一般的なC++コードを含むユースケースはありますか?
char ch = 'a';
std::cout << ch << '\n';
std::cout << +ch << '\n';
最初の挿入により、文字a
がに書き込まれcout
ます。2番目の挿入は、の数値をに書き込みch
ますcout
。しかし、それは少しあいまいです。+
これは、コンパイラーがオペレーターに統合プロモーションを適用することに依存しています。
単項-
との対称性は完全に役に立たないわけではありません。強調に使用できます。
const int foo = -1;
const int bar = +1;
また、オーバーロードされた単項演算を使用して、自明ではない計算を実行しながら、オペランドと同じ論理+
値を生成する演算を示すことができます。(これは、単項変換ではなく単項変換をオーバーロードできるAdaの型変換で行われるのを見てきました。)C ++の良い例がないので、スタイルが悪いと主張する人もいるかもしれません。(それから、私はオーバーロードについてたくさんの怒りを見てきました。)+
<<
C ++がそれを持っている理由に関しては、それはおそらく主にCとの一貫性のためであり、1989年のANSI規格でそれを追加しました。Cの理論的根拠は次のように述べています。
単項プラスは、単項マイナスとの対称性のために、いくつかの実装からC89委員会によって採用されました。
クラスの数値のセマンティクスを明示的に避けている場合、演算子のオーバーロードは「intのように行わない」ことは明らかです。その場合、単項プラスは意味を持ち、単に戻るだけではありません。*this
顕著な例:埋め込まれたEBNFのKleene Plusに対するBoost.Spiritの単項プラスは、引数(パーサールールも)を1回以上一致させるパーサールールを生成します。
単項+
演算子は、左辺値を右辺値に変換します。
struct A {
static const int value = 1;
};
// ...
int x = std::min(0, A::value);
ああ、いや!誰かが定義(および宣言)するのを忘れたため、このコードはリンクされませんA::value
。 std::min
引数を参照A::value
で受け取るため、参照がそれにバインドできるようにアドレスが必要です(技術的には、1つの定義規則では、プログラムで1回だけ定義する必要があります)。
気にしないでください、救助への単項プラス:
int x = std::min(0, +A::value);
単項プラスは同じ値の一時を作成し、参照は一時にバインドされるため、欠落している定義を回避できます。
これは頻繁に必要なものではありませんが、単項プラス演算子の実用的な使用法です。
単項+は統合プロモーションを適用します。@PeteBeckerの回答は、役立つ1つの方法を示しています。
もう1つは、スコープなしの列挙型が、内のすべての値を表すことができる整数型にプロモートされることに注意してください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 );
}
少し遅れましたが、これは私が偶然見つけた非常にねじれた使用法です。どうやら、この+
演算子は、空のプリプロセッサトークンに遭遇する可能性を回避するためのセーフガードを設計するときに(おそらく厳密には必要ではないにしても)役立つ可能性があります。より詳細な議論については、この投稿を参照してください。
それは実用的ですが、決して楽しいものではありません。
特に、+
ラムダを関数ポインターに変換します。通常、変換は自動的に行われますが、そうでない場合もあります。
たとえば、これはコンパイルされません。
std::array arr{
[](int x){return x*x;},
[](int x){return x*x*x;},
};
std::array
テンプレートパラメータとして関数ポインタ型を指定することで機能させることも、次のようにすることもできます。
std::array arr{
+[](int x){return x*x;},
+[](int x){return x*x*x;},
};
算術変数の場合、operator+は新しい値を生成するためです。これを使用して、参照のような(プロキシ)タイプの値のコピーを生成します。
template<class T> class ref_of{
T* impl_; // or a more complicated implementation
public:
T operator+() const{return *impl_;}
operator T&()&{return *impl_;}
}
別のオプションを使用するoperator*
ことref_of
もできますが、ポインターのようなオブジェクトと混同される可能性があります。
算術変数の場合、operator +は新しい値を生成するため、一般に、参照のような(プロキシ)タイプの値のコピーを生成するために使用します。
template<class T> class ref_of{
T* impl_; // or a more complicated implementation
public:
T operator+() const{return *impl_;}
operator T&()&{return *impl_;}
}
...
ref_of<T> r = t;
auto s = +r; // this forces a copy
別のオプションを使用するoperator*
ことref_of
もできますが、ポインターのようなオブジェクトと混同される可能性があります。