ユーザー定義リテラルがC ++に追加する新機能は何ですか?


139

C ++ 11を導入するユーザ定義リテラル既存のリテラルに基づいて新たなリテラル構文(の導入を可能にするinthexstringfloat任意のタイプのリテラルプレゼンテーションを持つことができるであろうように)。

例:

// imaginary numbers
std::complex<long double> operator "" _i(long double d) // cooked form
{ 
    return std::complex<long double>(0, d); 
}
auto val = 3.14_i; // val = complex<long double>(0, 3.14)

// binary values
int operator "" _B(const char*); // raw form
int answer = 101010_B; // answer = 42

// std::string
std::string operator "" _s(const char* str, size_t /*length*/) 
{ 
    return std::string(str); 
}

auto hi = "hello"_s + " world"; // + works, "hello"_s is a string not a pointer

// units
assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

一見、これはとてもクールに見えますが、サフィックス_ADを付け_BCて日付を作成しようと考えたときに、それが実際にどれほど適用可能か疑問に思っています。オペレーターの順序が原因で問題があることがわかりました。1974/01/06_AD最初に1974/01(プレーンints として)評価し、その後06_AD(8月と9月は8 0進数の理由でなしで記述する必要はない)だけを評価します。これは1974-1/6_AD、演算子の評価順序が機能するように構文を整えることで回避できますが、扱いにくいです。

だから私の質問の結論はこれです、あなたはこの機能がそれ自体を正当化すると思いますか?C ++コードを読みやすくするために、他にどのようなリテラルを定義したいですか?


2011年6月の最終ドラフトに合わせて構文を更新


8
これを閉じるために投票します。タイトルはかなり明らかに炎症を起こしています。
子犬

76
@DeadMG、タイトルに問題がある場合は編集できます。11の賛成票と8の賛成票を持つ3年前の質問をクローズしようとするのは少しおかしいです。(このサイトのエチケットが過去3年間に変更されたという言及はありません)。
Motti、2011年

5
あなたの例にエラーがあると思います:string operator "" _s(const char*s);"解析に使用することはできません"hello"_s"。これは文字列リテラルであり、追加のsize_tパラメーターを持つオペレーターを探します。私は正しいですか?
towi

1
私が不思議に思ってきたことの一つは、それがのようなタイプの交換、C ++での書き込み「ポータブルC」に理にかなっているかどうかでuint16_tその動作が実装依存である、類似したタイプとuwrap16し、unum16与えられたような振る舞いの実装に依存しないだろう、uwrap16 w=1; unum16 n=1;表情をw-2してn-2生じるであろう(uwrap16)65535(int)-1、それぞれ[ uint16_tシステム上の最初の結果生じるであろうint16ビットであり、およびシステム上の第二はどこintも大きいです]。私が見た最大の問題は、数値リテラルの処理でした。
スーパーキャット

1
数値リテラルを他の定義済みの振る舞いの数値型とスムーズに相互運用できるようにすると、実装に依存せずに実装に依存するアクションを実行したいコードがそうすることができる言語を作成するためにそのような型を使用できるようになるはずです-定義された動作。ポインターの違いやsizeof実装に依存する整数型を返すため、IDBが依然として避けられない場所がいくつかありますが、状況はそれよりもはるかに良くなる可能性があります。そのコンセプトについてどう思いますか?
スーパーキャット2015年

回答:


71

コンストラクター呼び出しの代わりにユーザー定義リテラルを使用する利点がある場合は次のとおりです。

#include <bitset>
#include <iostream>

template<char... Bits>
  struct checkbits
  {
    static const bool valid = false;
  };

template<char High, char... Bits>
  struct checkbits<High, Bits...>
  {
    static const bool valid = (High == '0' || High == '1')
                   && checkbits<Bits...>::valid;
  };

template<char High>
  struct checkbits<High>
  {
    static const bool valid = (High == '0' || High == '1');
  };

template<char... Bits>
  inline constexpr std::bitset<sizeof...(Bits)>
  operator"" _bits() noexcept
  {
    static_assert(checkbits<Bits...>::valid, "invalid digit in binary string");
    return std::bitset<sizeof...(Bits)>((char []){Bits..., '\0'});
  }

int
main()
{
  auto bits = 0101010101010101010101010101010101010101010101010101010101010101_bits;
  std::cout << bits << std::endl;
  std::cout << "size = " << bits.size() << std::endl;
  std::cout << "count = " << bits.count() << std::endl;
  std::cout << "value = " << bits.to_ullong() << std::endl;

  //  This triggers the static_assert at compile time.
  auto badbits = 2101010101010101010101010101010101010101010101010101010101010101_bits;

  //  This throws at run time.
  std::bitset<64> badbits2("2101010101010101010101010101010101010101010101010101010101010101_bits");
}

利点は、実行時例外がコンパイル時エラーに変換されることです。文字列を受け取るビットセットctorに静的アサートを追加することはできませんでした(少なくとも文字列テンプレート引数がない場合は)。


7
std :: bitsetに適切なconstexprコンストラクターを指定することで、同じことを行うことができます。
Nicol Bolas 2013年

1
@NicolBolasそうですね。私は実際にそこにいないことに驚いています。手遅れではないのであれば、2014年に1つまたは2つを提案する必要があります。
emsr 2013年

192

一見、それは単純な構文糖のようです。

しかし、より深く見ると、C ++ユーザーのオプションを拡張して、個別の組み込み型とまったく同じように動作するユーザー定義型を作成できるため、構文糖度以上のものであることがわかります。この点で、この小さな「ボーナス」は、C ++への非常に興味深いC ++ 11の追加です。

C ++で本当に必要なのでしょうか?

過去数年に私が書いたコードはほとんど使用されていませんが、C ++で使用しなかったからといって他のC ++開発者にとって興味がないという意味ではありません。

C ++(およびCではそうです)、コンパイラー定義のリテラルを使用して、整数を短整数または長整数、実数を浮動小数点または倍長(または倍長整数)として入力し、文字列を通常またはワイド文字として入力しました。

C ++では、オーバーヘッド(インライン化など)を潜在的に発生させずに、独自の型(クラス)を作成する可能性がありました。演算子を型に追加して、それらを同様の組み込み型のように動作させることができました。これにより、C ++開発者は、行列自体や複素数を、言語自体に追加された場合と同じように自然に使用できます。キャスト演算子を追加することもできます(通常、これは悪い考えですが、適切な解決策になる場合もあります)。

ユーザー型を組み込み型として動作させるには、ユーザー定義のリテラルという1つの点が見落とされていました。

したがって、言語の自然な進化であると思いますが、できるだけ完全にする必要があります。「型を作成し、組み込み型と同じように動作させたい場合は、次のツールを使用してください。 .. "

私は、すべてのプリミティブをブール、整数などを含む構造体にして、すべての構造体をオブジェクトから派生させるという.NETの決定と非常に似ていると思います。この決定だけでも、プリミティブを使用する場合、JavaがJavaの仕様に追加するボクシング/アンボクシングの量に関係なく、.NETはJavaの範囲をはるかに超えています。

C ++で本当に必要ですか?

この質問はあなたが答えることです。Bjarne Stroustrupではありません。ハーブサッターではありません。C ++標準委員会のメンバーはいません。これがC ++で選択できる理由ですでであり、有用な表記を組み込み型だけに制限しません。

場合は、あなたがそれを必要とし、それは歓迎の追加です。場合あなたがない、よく...それを使用しないでください。それはあなたに何もかかりません。

機能がオプションである言語であるC ++へようこそ。

むくんだ???あなたの複合体を見せてください!!!

肥大化と複雑な(しゃれ意図)の違いがあります。

Nielsが示したように、ユーザー定義リテラルはC ++にどのような新しい機能を追加しますか?、複素数を記述できることは、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では、組み込み型として別の型を追加し、組み込み演算子のオーバーロードサポートを追加しました。そして、別の組み込みリテラル機能を追加しました。

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日付を選択しますが、それはあなたのニーズに依存します。これは、ユーザーが独自のリテラル名を定義できるようにするための重要なポイントです。


1
ありがとう、私と私の別の性格が発見されました。もっと真剣に、私はこれを一人で書きましたが、おそらく私は私の母国語の表現を使用していて、それらは英語にうまく翻訳されません。
paercebal 2008年

タイトルが示す「別パーツ」については、申し訳ありませんが、かなり長い記事で構成されていると思います。太字のテキストは、自分がいる段落の要約です。正当な理由なしに情報だけが欲しい人は、タイトルと太字のテキストの読みを制限できます。
paercebal 2008年

3
+1。本当にいい説明。これが実装されるのを待っています。それは私たちにとって本当に重要です。私たちはMDE(Model-Driven Engineering)に取り組んでおり、これが必要だと思います。私たちのケースを説明するために、以下の応答を追加しています。
ディエゴセビリア

9
@TGV::you can write 1+2i, but you still can't write a+bi, so there's absolutely no pointあなたのa+bi例を無視するのはばかげていますが、あなたがそれを「低頻度」として認識するという事実は、誰もがそうすることを意味するわけではありません。。。全体像を見ると、重要なのは、組み込み型と同様に、ユーザー定義オブジェクトをできるだけ言語の第一級市民と見なすことができるようにすることです。あなたが書くことができるのであれば、1.5fそして1000UL、なぜあなたは書くことができなかった25iにもか100101b?CやJavaとは逆に、ユーザー型はC ++言語の二級市民とは見なされません。
paercebal 2011年

3
@Anton::Most of data still comes from IOコードには多くのハードコードされた値があります。すべてのブール値を見て、すべての整数、書くことがより便利であるので、コードに来るすべてのダブルスのx = 2 * y ;代わりにx = Two * yどこTwo、厳密に型指定された定数。ユーザー定義のリテラルを使用すると、その上に型を配置して、次のように記述できます。x = 2_speed * y ;そして、計算に意味があることをコンパイラーに検証させます。。。それはすべて強いタイピングについてです。。。おそらくあなたはそれを使わないでしょう。しかし、仕事でC ++ 11対応のコンパイラーを使用できるようになるとすぐに、私は確信します。
paercebal 2013年

36

数学コードにはとてもいいです。私の頭の中では、次の演算子の使用を見ることができます:

度の場合はdeg。これにより、絶対角度を書くことがより直感的になります。

double operator ""_deg(long double d)
{ 
    // returns radians
    return d*M_PI/180; 
}

また、さまざまな固定小数点表現(DSPおよびグラフィックスの分野で現在も使用されています)にも使用できます。

int operator ""_fix(long double d)
{ 
    // returns d as a 1.15.16 fixed point number
    return (int)(d*65536.0f); 
}

これらは使い方の良い例のように見えます。コード内の定数を読みやすくするのに役立ちます。これもコードを読みにくくするためのツールの1つですが、すでに多くのツールを悪用しているため、もう1つ使用してもそれほど害はありません。


1
「しかし、私たちはすでにツールを乱用しているので、もう1つ使ってもそれほど害はありません。」うわー、最近のc ++ [x] 1234567890機能の洪水の背後にある哲学ではないことを願っています。これらすべてを使用するライブラリと、構成用の10個のファイル形式、およびコードの前処理と後処理用の2つのツールを学習する必要があると想像してください...
masterxilo

@masterxiloもちろん、実際にはあなたの例はばかげています。UDLは関数よりも学ぶのが難しくありません。UDLはそれらの構文糖子だけです-さらに、優れたlibはUXを改善するために必要な機能のみを使用します-それを正確に文書化しますぜひ。誰かが機能を使いすぎて判読不能なコードを生成した場合(それが彼らの一連の作業で完全に回避可能であると想定している場合...)、それはその機能に問題があるのではなく、使用方法です。さらに、ある人の読めない人は、別の人のパンとバターです。すべての意見-&オプションです。気に入らなくても心配はいりません。それらを使用する必要はありません。他の人ができます。
underscore_d

17

UDLは名前空間を持ちます(宣言/ディレクティブを使用してインポートできますが、のようなリテラルを明示的に名前空間にすることはできません3.14std::i)。

それらが実際にテンプレート化(およびconstexpr'd)できるという事実は、UDLでかなり強力なことを実行できることを意味します。Bigintの作者は、コンパイル時に(constexprまたはテンプレートを介して)計算された任意の大きな定数を最終的に持つことができるので、本当に幸せになります。

私たちは同じように、(その様子から)標準で夫婦便利リテラルを見ていないということだけで悲しいsstd::stringi虚数単位のために。

UDLによって節約されるコーディング時間は実際にはそれほど長くありませんが、可読性が大幅に向上し、より多くの計算をコンパイル時間にシフトして実行を高速化できます。


名前空間について要点を明確にしてくれてありがとう...私はそれを疑問に思っていました。
ネイサンリード

12

少しコンテキストを追加しましょう。私たちの作業では、ユーザー定義のリテラルが大いに必要です。MDE(Model-Driven Engineering)に取り組んでいます。C ++でモデルとメタモデルを定義したいと考えています。EcoreからC ++へのマッピングを実際に実装しました(EMF4CPP)。

問題は、モデル要素をC ++のクラスとして定義できる場合に発生します。メタモデル(Ecore)を引数付きのテンプレートに変換するアプローチを取っています。テンプレートの引数は、型とクラスの構造的特性です。たとえば、2つのint属性を持つクラスは次のようになります。

typedef ::ecore::Class< Attribute<int>, Attribute<int> > MyClass;

ただし、モデルまたはメタモデルのすべての要素には通常名前が付いていることがわかります。私たちは書きたいと思います:

typedef ::ecore::Class< "MyClass", Attribute< "x", int>, Attribute<"y", int> > MyClass;

ただし、文字列はテンプレートへの引数として禁止されているため、C ++、C ++ 0xはこれを許可しません。文字ごとに名前を書くことができますが、これは確かに混乱です。適切なユーザー定義のリテラルを使用して、同様の何かを書くことができます。「_n」を使用してモデル要素名を特定するとします(正確な構文は使用していません。アイデアを出すためだけです)。

typedef ::ecore::Class< MyClass_n, Attribute< x_n, int>, Attribute<y_n, int> > MyClass;

最後に、これらの定義をテンプレートとして使用すると、モデル要素、モデル変換などをトラバースするためのアルゴリズムを設計するのに非常に役立ちます。これは、型情報、識別、変換などがコンパイル時にコンパイラによって決定されるためです。


4
私はこの部分がとても好きby the compiler at compile timeです... :-)
paercebal

12

Bjarne Stroustrupが、このC ++ 11トークの UDLについて、型が豊富なインターフェイスの最初のセクションで、約20分で語っています。

UDLに関する彼の基本的な議論は三段論法の形をとります:

  1. 「トリビアル」タイプ、つまり組み込みプリミティブタイプは、些細なタイプエラーのみをキャッチできます。より豊富な型のインターフェースにより、型システムはより多くの種類のエラーをキャッチできます。

  2. 豊富に型付けされたコードがキャッチできる種類のエラーは、実際のコードに影響を与えます。(彼は、重要な定数の寸法誤差のために悪名高く失敗した火星気候オービターの例を示します)。

  3. 実際のコードでは、単位はほとんど使用されません。ランタイムコンピューティングまたはメモリオーバーヘッドが発生してリッチタイプを作成するのは非常にコストがかかり、既存のC ++テンプレート化されたユニットコードを使用するのは非常に面倒なので、誰もそれを使用しないため、人々はそれらを使用しません。(経験的に、ライブラリーが10年間使用されているにもかかわらず、だれもそれを使用しません)。

  4. したがって、エンジニアが実際のコードでユニットを使用できるようにするには、(1)ランタイムオーバーヘッドが発生せず、(2)表記上許容できるデバイスが必要でした。


9

必要なのは、コンパイル時のディメンションチェックのサポートだけです。

auto force = 2_N; 
auto dx = 2_m; 
auto energy = force * dx; 

assert(energy == 4_J); 

たとえば、コンパイル時の次元分析および単位/数量の操作と変換については、小さなC ++ 11、C ++ 14ヘッダー専用ライブラリであるPhysUnits-CT-Cpp11を参照してください。Boost.Unitsよりもシンプルで、m、g、sなどの単位記号リテラル、m、k、Mなどのメトリックプレフィックスをサポートし、標準C ++ライブラリ、SIのみ、次元の整数乗にのみ依存します。


または、Nic Holthausによる依存関係のないc ++ 14で構築された、コンパイル時のヘッダーのみの次元分析および単位変換ライブラリであるunitsを参照してください。
Martin Moene

6

うーん...この機能についてはまだ考えていません。あなたのサンプルはよく考え抜かれ、確かに興味深いものです。現在のようにC ++は非常に強力ですが、残念ながら、読み取るコードの一部で使用される構文は、非常に複雑な場合があります。すべてではないにしても、少なくとも読みやすさは重要です。そして、そのような機能はより読みやすくするためのものです。私があなたの最後の例をとるなら

assert(1_kg == 2.2_lb); // give or take 0.00462262 pounds

...今日はどう表現するのだろう。KGクラスとLBクラスがあり、暗黙のオブジェクトを比較します。

assert(KG(1.0f) == LB(2.2f));

そして、それも同様です。長い名前を持つ型や、アダプターを作成するためのこのような素晴らしいコンストラクターが期待できない型の場合、オンザフライの暗黙的なオブジェクトの作成と初期化に優れた追加になる可能性があります。一方、メソッドを使用してオブジェクトを作成および初期化することもできます。

しかし、数学についてはニルスに同意します。たとえば、CおよびC ++の三角関数は、ラジアンでの入力を必要とします。でも私は程度で考えるので、Nilsが投稿したような非常に短い暗黙の変換はとてもいいです。

結局のところ、それは構文上の砂糖になるでしょうが、読みやすさにはわずかな影響があります。そして、おそらくいくつかの式も書く方が簡単でしょう(sin(180.0deg)はsin(deg(180.0)よりも簡単です)。そして、この概念を悪用する人々もいます。しかし、言語を乱用する人々は、 C ++ほど表現力豊かなものではなく、非常に限定的な言語。

ああ、私の投稿では基本的にそれ以外は何も言われていません。大丈夫です。影響はそれほど大きくありません。心配しないでください。:-)


5
括弧がアンバランスです!私のOCDも私を嫌っています。
X-Istence 2008年

3

私は必要ありませんか(これは可能性があり、この機能を望んでいたことがないブラブの効果)。私のひざの反応は、それが不十分であり、追加として解釈される可能性のあるすべての操作に対してoperator +をオーバーロードするのがクールだと考える同じ人々にアピールする可能性が高いです。


確認:非常に興味深い記事。
paercebal 2008年

2

C ++は通常、使用される構文について非常に厳密です。プリプロセッサを除いて、カスタム構文/文法を定義するために使用できるものはあまりありません。たとえば、既存のオペラをオーバーロードすることはできますが、新しいオペラを定義することはできません。IMOは、C ++の精神に非常によく似ています。

よりカスタマイズされたソースコードを作成する方法をいくつか気にしませんが、選択したポイントは非常に孤立しているようで、私は最も混乱しています。

意図された使用でさえ、ソースコードを読むのをはるかに難しくするかもしれません:単一の文字は、文脈から決して特定することができない広大な副作用を持っているかもしれません。u、l、fの対称性により、ほとんどの開発者は1文字を選択します。

これはスコーピングを問題に変える可能性もあります。グローバル名前空間で単一の文字を使用することはおそらく悪い習慣と考えられ、ライブラリを簡単に混合できると思われるツール(名前空間と説明的な識別子)はおそらくその目的を無効にします。

「自動」と組み合わせて、またブーストユニットなどのユニットライブラリと組み合わせて、いくつかのメリットを確認しますが、この機能には十分ではありません。

しかし、私たちが思いついた賢いアイデアは何でしょうか。


1
using single letters in global namespace will probably be considered bad practiceしかし、それは関連性がありません:(A)UDLは(非グローバル)ネームスペーススコープで定義する必要があります...おそらく(B)UDLは、文字だけでなく、アンダースコアと1以上の文字で構成されている必要があるためです。グローバルNSは実装用に予約されています。これは、UDLが本質的に混乱を生むという考えに対して少なくとも2ポイントです。機能のユーティリティを削減する名前空間をスコープ指定する必要があるので、たとえば、inline namespace必要に応じてユーザーがホールセールをインポートできるようにstdlibがそれらをsで宣言するのはそのためです。
underscore_d

2

次のようなバイナリ文字列にユーザーリテラルを使用しました。

 "asd\0\0\0\1"_b

文字列を半分にカットしないstd::string(str, n)ようにコンストラクタを使用し\0ます。(プロジェクトはさまざまなファイル形式で多くの作業を行います。)

これはstd::string、のラッパーを優先して破棄した場合にも役立ちましたstd::vector


-5

その中でのラインノイズは巨大です。また、読むのは恐ろしいことです。

知らせてください、彼らは何らかの例を伴う新しい構文の追加を推論しましたか?たとえば、彼らはすでにC ++ 0xを使用しているいくつかのプログラムを持っていますか?

私にとって、この部分:

auto val = 3.14_i

この部分を正当化しない:

std::complex<double> operator ""_i(long double d) // cooked form
{ 
    return std::complex(0, d);
}

他の1000行でi-syntaxを使用する場合でも同様です。あなたが書く場合、おそらくそれに沿って何か別の10000行を書くでしょう。特に、おそらくほとんどどこにでもこれを書くとしたら、

std::complex<double> val = 3.14i

'auto'キーワードは正当化されるかもしれませんが、おそらくそうです。ただし、この点ではC ++ 0xよりも優れているため、C ++だけを取り上げます。

std::complex<double> val = std::complex(0, 3.14);

それは..そのように単純です。あなたがどこでもそれを使うならば、すべての標準と先のとがったブラケットがただ不自由であるとさえ考えました。std :: complexをcomplexに変換するためのC ++ 0xの構文を推測し始めません。

complex = std::complex<double>;

これは簡単なことかもしれませんが、C ++ 0xではそれほど単純ではないと思います。

typedef std::complex<double> complex;

complex val = std::complex(0, 3.14);

たぶん?> :)

とにかく、ポイントは次のとおりです。std:: complex(0、3.14);の代わりに3.14iを記述します。いくつかの特別な場合を除いて、全体的に多くの時間を節約することはできません。


10
@Cheery:あなたにとって、「auto val = 3.14i」はそれをサポートするために書かれたコードを正当化しません。「printf( "%i"、25)」は、printf用に書かれたコードを正当化しません。パターンが見えますか?
paercebal 2008年

5
@Cheery:「その中のラインノイズは巨大です」。いいえ、そうではありません...「また読むのはひどい」。あなたの主観的な議論は興味深いですが、この機能のコードが驚くべき/衝撃的ではないことを確認するには、一般的に演算子のオーバーロードを見てください... C ++開発者にとって
paercebal

3
autoは読みやすさを向上させます。forループでインターレーターを使用することを検討してください:for(auto it = vec.begin(); it!= vec.end(); ++ it)... for_eachについては知っていますが、それを使用するためのファンクターを作成する必要はありません。
KitsuneYMG 2009年

1
@kts:C ++ 1xの場合、ラムダと範囲があります
Joe D

3
C ++のラインがC ++ 0xよりも優れている場合、私のラインはさらに優れています。書きます:std::complex<double> val(0, 3.14);
Ben Voigt、2011
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.