一見すると、単純なシンタックス シュガーのように見えます。
しかし、より深く見てみると、C++ ユーザーのオプションを拡張して、別個の組み込み型とまったく同じように動作するユーザー定義型を作成するため、これは構文糖衣以上のものであることがわかります。この小さな「おまけ」は、C++ への非常に興味深い C++11 の追加です。
本当に C++ で必要ですか?
過去数年間に書いたコードにはほとんど使用されていませんが、C++ で使用しなかったからといって、別の C++ 開発者にとって興味深いものではないということにはなりません。
C++ (およびおそらく C) では、コンパイラ定義のリテラルを使用して、整数を short または long 整数として、実数を float または double (または long double) として、文字列を normal または wide char として型付けしていました。 .
C++ では、潜在的にオーバーヘッド (インライン化など) なしで、独自の型 (つまり、クラス) を作成する可能性がありました。型に演算子を追加して、同様の組み込み型のように動作させることができました。これにより、C++ 開発者は、行列と複素数が言語自体に追加されている場合と同じように自然に使用できるようになります。キャスト演算子を追加することもできます (これは通常は悪い考えですが、場合によっては正しい解決策です)。
ユーザー型を組み込み型として動作させるために、まだ 1 つのことを見逃していました。それは、ユーザー定義のリテラルです。
したがって、これは言語の自然な進化だと思いますが、可能な限り完全にするために、「型を作成し、それを組み込み型として可能な限り動作させたい場合は、ここにツールがあります。 ..」
ブール値、整数などを含むすべてのプリミティブを構造体にし、すべての構造体をオブジェクトから派生させるという.NETの決定と非常に似ていると思います。この決定だけでも、プリミティブを扱う場合、.NET は Java の範囲をはるかに超えたものになります。Java がその仕様にどれだけボックス化/ボックス化解除のハックを追加しようとも。
あなたは本当にC ++でそれを必要としますか?
この質問はあなたが答えるものです。Bjarne Stroustrup ではありません。ハーブサッターではありません。C++ 標準委員会のメンバーではありません。これが、 C++ で選択できる理由であり、組み込み型だけに有用な表記法を制限しません。
あなたがそれを必要とするなら、それは歓迎すべき追加です。そうでない場合は、使用しないでください。それはあなたに何もかかりません。
機能がオプションである言語、C++ へようこそ。
むくんだ???コンプレックス見せて!!!
肥大化したものと複雑なものには違いがあります (しゃれが意図されています)。
ユーザー定義リテラルが C++ に追加する新しい機能についてNiels が示したように? 、複素数を記述できることは、C および C++ に「最近」追加された 2 つの機能の 1 つです。
// C89:
MyComplex z1 = { 1, 2 } ;
// C99: You'll note I is a macro, which can lead
// to very interesting situations...
double complex z1 = 1 + 2*I;
// C++:
std::complex<double> z1(1, 2) ;
// C++11: You'll note that "i" won't ever bother
// you elsewhere
std::complex<double> z1 = 1 + 2_i ;
現在、C99 の「double complex」型と C++ の「std::complex」型の両方で、演算子のオーバーロードを使用して、乗算、加算、減算などを行うことができます。
しかし、C99 では、別の型が組み込み型として追加され、組み込み演算子のオーバーロード サポートが追加されました。そして、組み込みのリテラル機能がもう 1 つ追加されました。
C++ では、言語の既存の機能を使用しただけで、文字どおりの機能が言語の自然な進化であると判断し、それを追加しました。
C では、別のタイプに同じ表記の拡張が必要な場合、量子波関数 (または 3D ポイント、または作業分野で使用している基本的なタイプ) を組み込み型としての C 標準は成功します。
C++11 では、自分で実行できます。
Point p = 25_x + 13_y + 3_z ; // 3D point
肥大化していますか?いいえ、C と C++ の両方のコンプレックスがリテラルのコンプレックス値を表現する方法を必要としていることが示すように、その必要性はあります。
設計が間違っていませんか?いいえ、拡張性を考慮して、他のすべての C++ 機能と同様に設計されています。
表記のみですか?コードにタイプ セーフを追加することもできるため、いいえ。
たとえば、CSS 指向のコードを想像してみましょう。
css::Font::Size p0 = 12_pt ; // Ok
css::Font::Size p1 = 50_percent ; // Ok
css::Font::Size p2 = 15_px ; // Ok
css::Font::Size p3 = 10_em ; // Ok
css::Font::Size p4 = 15 ; // ERROR : Won't compile !
これにより、値の代入に強力な型付けを適用することが非常に簡単になります。
は危険ですか?
良い質問。これらの関数に名前空間を付けることはできますか? もしそうなら、ジャックポット!
何事もそうですが、道具の使い方を誤ると自殺する可能性があります。Cは強力で、Cガンを誤用すると頭を撃ち落とすことができます. C++ には C 銃がありますが、メス、テーザー、およびツールキットにあるその他のツールも含まれています。メスを誤用すると、出血して死ぬ可能性があります。または、非常にエレガントで堅牢なコードを構築できます。
すべての C++ 機能と同様に、本当に必要ですか? これは、C++ で使用する前に答えなければならない質問です。そうしないと、費用はかかりません。しかし、本当にそれが必要な場合、少なくとも言語はあなたを失望させません.
日付の例?
あなたのエラーは、私には思えますが、演算子を混在させていることです:
1974/01/06AD
^ ^ ^
/ は演算子であるため、コンパイラはそれを解釈する必要があるため、これを回避することはできません。そして、私の知る限り、それは良いことです。
あなたの問題の解決策を見つけるために、リテラルを別の方法で書きます。例えば:
"1974-01-06"_AD ; // ISO-like notation
"06/01/1974"_AD ; // french-date-like notation
"jan 06 1974"_AD ; // US-date-like notation
19740106_AD ; // integer-date-like notation
個人的には、整数と ISO の日付を選択しますが、それはあなたのニーズによって異なります。これが、ユーザーが独自のリテラル名を定義できるようにすることの要点です。