1 :
デフォルトの名無しさん :
2005/03/28(月) 21:06:30 ,,,,,,,,,,,,,,,,,,の使い方を極めよう。 漢なら。
えぴすてーめー氏の記事でなんかみたことあるな おー、こういう使い方もできるのかと ( ・∀・)つ〃∩ 80ヘェくらい
3 :
デフォルトの名無しさん :2005/03/28(月) 21:57:02
なにそれ
カンマを極めたら何が出来るようになるんだ?
5 :
デフォルトの名無しさん :2005/03/28(月) 22:05:30
常に exp2 の値を返します。ただし、代入演算子(=など)よりも優先度が低いため、xx = 1, 2; は (xx = 1), 2; と解釈されるので注意してください。また、関数の引数にカンマ(,)を用いた場合は、カンマ演算子とは解釈されません。 for (i = 0, j = 0; i < 10; i++) { : }
カンマ演算子を使うと、2つの処理をセットにできます。カンマ演算子をよく使う場面はfor文です。 for(i=0,j=10; i<10; ++i,--j) のように使います。最初に、変数iに0が、変数jに10が代入されます。その後、毎ループごとに、変数iはインクリメント、変数jはデクリメントされます。これらの処理はセットになったということです。 また、変数の宣言を、 int i, j, k; のようにできますが、これもカンマ演算子の1つの使い方といえます。つまり、変数iもjもkもセットで宣言する、という意味です。
7 :
デフォルトの名無しさん :2005/03/28(月) 22:13:29
Q 【値の交換】 a ^= b ^= a ^= b というコードを使えば、 a と b の値を交換することができることを動作確認した。しかし、この書き方はよくないと言われた。なぜか。 A これはトリッキーなコードとして非常に有名です。 a^a が0になることを利用している所がポイントです。しかし、見てすぐ分かるように、一つの式の中に副作用が複数回あり、従って、この結果は未定義となります。 次のようにカンマで区切って書くと、副作用の影響は消滅します。なぜなら、カンマ演算子は、左から右に評価すると仕様で決められているからです。 a ^= b, b ^= a, a ^= b しかし、これでもなお、このコードは同一のオブジェクトに対して動作しない (aとaを交換するとどんな値になるか?)という欠点があるため、実際にプログラムに使うのは止めておいた方が無難でしょう。
8 :
デフォルトの名無しさん :2005/03/28(月) 22:17:10
Q 【&&や||と副作用完了点】 && や || を使ったコードの中には、評価順序が左から右という前提で書かれているものがあるが、 評価順序は不定ではないのか。 A 例外として、評価順序が決まっている演算子があります。 && 、 || 、 カンマ演算子の「 , 」、三項演算子の「 :? 」です。これらは、左を評価し、 その後に右が評価されることになります。 ある時点においてそこまでの副作用が全て完了することが保証されている 区切りのことを、副作用完了点(sequence point)と呼びます。前述の演算子は、 左の式を評価した直後が副作用完了点となっています。 つまり、左が処理し終わってから右が処理されることが保証されているわけです。 なお、関数の引数を区切るのに使うカンマは、カンマ演算子ではないため、 評価順序は不定です。
でも自分でoperator || とか定義しちゃったら、順番の保障はなくなるよね?
さらにカンマ演算子もオーバーロードできる罠。
11 :
デフォルトの名無しさん :2005/03/28(月) 22:29:05
char a[4] = "ABCD"; という初期化は、'\0' も含めて 5 文字分必要では? ANSI C なら必要ない。 要素数が指定されている char 型配列の初期値として "ABCD" が使われた場合は、 { 'A', 'B', 'C', 'D' } の省略記法とみなされる。従って「すでに 5 バイトある」ということにはならない。また、初期値の個数が配列の要素数より多い場合はエラーなので、他の変数を破壊するという心配は無用である。
12 :
デフォルトの名無しさん :2005/03/28(月) 22:35:01
>カンマ演算子もオーバーロードできる罠。 しらんかった。
void log_output( char *msg ); ↑こんなログ出力関数があったとする。 これを使って、プログラムのトレースをしたいとする。 その際、重要度に応じてログレベルを指定して、出力するログの量を加減したい。そこで、こんな方法。 ===================================================================== #define LOG_LEVEL 5 #define TRACE( msg, lvl ) ( ( lvl ) <= LOG_LEVEL ? log_output( ( msg ) ), 0 : 0 ) void foo1( void ) { TRACE( "FOO1-1", 1 ); ; TRACE( "FOO1-2", 5 ); } void foo2( void ) { TRACE( "FOO2-1", 1 ); ; TRACE( "FOO2-2", 10 ); } ===================================================================== TRACE マクロの、第二パラメータがログレベルになっている。 LOG_LEVELで定義する値が基準となり、これより大きいログレベルのTRACEは、コード生成されない。 上記の例では、4つのTRACEのうち、最後のものだけが、コード化されない。 TRACE マクロは、三項演算子に展開されるのだが、条件判定後実行される評価式は以下のようになっている 真 : log_output( msg ), 0 偽 : 0 偽の場合、定数 0 を返すのみ。つまりTRACEマクロは、プログラム中で何の作用もない定数だけの文となり、コンパイラに無視される。 真の場合、カンマ演算子が使われており、log_outputをコールした後、定数 0 を返す。 目的は log_output をコールすることだが、困ったことにこの関数は返り血が void になっている。 三項演算子では、評価式が値を返さないとコンパイルエラーになってしまうのである。 そこで、真の評価式で void 型関数をコールしたい場合には、カンマ演算子で適当な値を返してやればよい。
boost assign libraryのoperator+=の実装は面白かった。 vector<int> v; v += 1, 2, 3, 4, 5, 6; とか…
>>6 >また、変数の宣言を、
>int i, j, k;
>のようにできますが、これもカンマ演算子の1つの使い方といえます。
(`・ω・´)
で、char* a, b, cと書いてハマると。
>>17 馬鹿対策のために、そういう変数宣言は禁止されてるな。
typedefしててもダメなんだよな、馬鹿がそれ見て
char* a, b, c ;
なんて書いたりするから、そういう書き方ができることすら、知られないようにする必要がある。
16が言ってるのはそういうことじゃなくて int i,j,k;のカンマは演算子じゃないってことだと思うが
2665年?皇紀?
21 :
デフォルトの名無しさん :2005/04/09(土) 22:19:07
エイプリルフールで日付が変わっただけ。 格闘技板ではホースト生誕40年とか 自作板ではAMD暦とか、色々あった。
22 :
デフォルトの名無しさん :2005/04/10(日) 09:47:38
マクロに複数の式や関数を書くときにも役に立つ。 それがカンマ演算師。
24 :
デフォルトの名無しさん :2005/04/13(水) 14:11:45
ちょっとしたSyntax sugar template<typename T> std::list<T>& operator , (std::list<T>& l, const T& t) { l.push_back(t); return l; } template<typename T> std::vector<T>& operator , (std::vector<T>& v, const T& t) { v.push_back(t); return v; } void foo(const std::list<int>& intlist); foo((std::list<int>(), 1, 2, 3, 4, 5));
>25 list<int> l = list<int>(), 1, 2, 3, 4, 5;
まんまBoost Assignment Libraryじゃないか
boostとか見てると、もうアホかと。 C++自体の言語仕様を拡張したほうがいいのに、 STL作った連中はトリッキーな手法で問題を解決しようとしてる。 そりゃ言語仕様を拡張したらコンパイラにも手を入れる必要が出てしまう。 世の中の数多くのコンパイラに変更を強いるよりも、 コンパイラは変えないで済むなら変えないほうがいいという考え方もあるだろう。 でも思い出してくれ。 C++は当初コンパイラはなく、 C++のソースからCのソースを出力するトランスレータで実現されていたことを。 C++の範囲内で工夫するよりも、 C++を拡張したC++++という言語を作って、 C++++のソース化らC++のソースを出力するトランスレータを使えばいいんだよ。
29 :
デフォルトの名無しさん :2005/05/24(火) 21:58:51
最終的に+いくつ付くんだ
>>28 >>30 C# って、漏れの目には
++
++
に見える。+がよっつついたのがC#なんだよ。
┼ ┼ こう斜めに重なって # になったというのを、 タバコ屋のおばちゃんから聞いたことがある。
音楽の記号で半音上げる意味から来てんのかと思ってた
>>33 ならば#ではなく♯と表記せねば。
…だが7bit系では無理。
JIS
UTF-7
C#って読みはシーシャープなのに表記はC#が正しいんだよな。 この板見てたらC♯って表記が目立つけど。
全角文字の方が正しいのか?
C♯も全角文字だが?
そうじゃねーよ。 外人が作ったのに、全角表記が正しいのかってことだよ。
>外人が作ったのに、全角表記が正しいのかってことだよ。 >外人が作ったのに、全角表記が正しいのかってことだよ。 >外人が作ったのに、全角表記が正しいのかってことだよ。 >外人が作ったのに、全角表記が正しいのかってことだよ。 >外人が作ったのに、全角表記が正しいのかってことだよ。
C# 2文字とも半角ですが何か。
井桁だって、慣例的にシャープと読んできたやん それでEやん
>>46 そうかい?
俺はシャープと読むのは恥ずかしいからよしておけと
言われてたが。
C#が出るまでの話だがな……。
つまり「#をシャープと読むのは恥ずかしいからよしておけ」と公言してた香具師のほうが 恥かしい香具師だったってことだな。
#をシャープと読むのはいいけど、#をシャープと読むのは如何なものかと思う。 シャープは♯だ。
確かにシャープは♯だ でもシーシャープはC♯ではなく、C#だ
C井を
C丼
だーかーらー、全角で書くな。
C‡‡
で、カンマはどこいったんだ?
>>55 普通は外人が読めなくなる
どっちでもいいとか言ってる奴に限って
デフォルトエンコードがSJISだったりして
日本語を読めるのは日本人だけなのか?
つーか ここに日本語で書くのと、C#を全角で書くかどうかは別問題だろ しかもスレ違い
シーシャープって読まなかったら シー井桁とでもよむんですかい?
>>60 >>55 は「外人が読めなくなる」としか言ってないんだが、何が別問題だ?
日本語が読める環境ならどっちでもいいだろうし、C#が読めないような環境なら日本語も読めない。
完全に同じ問題だ。
大体C#の日本語の正式名称は「プログラム言語C#」で、C#とは書いてない
ま、「表記」はロゴじゃないんだし全角か半角かなんて話は関係ないがな。
while ((a = func(...)) != hogegege) { ... } みたいな書き方ってよくするけど while (a = func(...), a != hogegege) { ... } ってした方が読みやすくね? aを2回書くのが面倒か、そうか。
>>65 音読してみることをお勧め。
・funcを呼び出した結果をaに入れ、その値がhogegegeじゃなかったら
・funcを呼び出した結果をaに入れ、aがhogegegeじゃなかったら
#あ、大差ないじゃんw
>>66 まぁこういうのは人によるんだろうけど、俺の場合は
上だといきなり「funcの戻り値とhoghogeの比較」という思考に至れるのに対して、
下だとhogehogeの比較の時に、ほんの一瞬、マジで一瞬のことだけど、
「aって何だっけ? ああそうだfuncの戻り値だ」
という余分な思考コストがかかるな。
68 :
66 :2005/07/09(土) 23:07:21
>>67 判ります。>66ではわざと大差ないと書いたけど、その僅かな違いが余計な思考コストになるんですよね。
漏れは一瞬だけ、 funcの返り値をaに代入できたかどうかを評価してその真偽とhogehogeが一致しなければ に見える。 真偽を==や!=で比較しちゃいけないから、そもそもそんな読み方はありえないけど。
夜中にこっそり while (a = (func(...) != hogegege)) { ... } に書き直してやる!
71 :
デフォルトの名無しさん :2005/08/04(木) 14:49:35
ifとかwhileって if(int value = func()); if(value >= 1,value <= 100); 見たいな書き方できるけど if(int value_one = func(),value_two = func()); 見たいにカンマ区切りで変数を複数宣言する事が出来ねぇだ。 何でこんな仕様なんだろ?
そこでは式は許されるが、宣言しちゃいけないからだよ。 そのローカル変数のスコープはどうなる?
>>71 そういやなんで for だけは許されてるんだろうな。
whileとの差別化。
>>72 複数できないだけで宣言そのものは出来るよ。
if(int value = 0)
{
変数のスコープ
}
見たいに。
>>75 知らなかった。
そんなこと出来るんだ。
でもforだと
for (inti i=0; i<100; i++) hoge(i);
の後もiが生きててなんか気持ち悪い。
vc++のデバッグモードでみてるとiが沢山いるんだょ。
c風に先頭で宣言して使いまわすべきなのか。
>>76 それはVC6が古い所為。
VC7.1なら今の言語仕様通りfor文の外では無効になる。
#ただし、互換性のためにオプションで切り替えることになる。
>>76 #define for if (0) else forってやると現行の仕様どおりのスコープになる。
特に意味ないがコンマでこんな事も出来る。 if(int value = func(value)) int a = value,b = func(a),func2(int),(*pfunc)(int) = func2,c = pfunc(b); By BCC 最後のcの位置だけはどうしても用途が無い。 なんか用途あったらキボンヌ。
個人的にはスコープは{}と対応していないと気持ち悪いな。 { int i ; for(;;){}} でいいじゃないか。
関数はいいのか
カンマ演算子って、for文の更新条件を複数書くために苦し紛れに導入したって感じがして好かない。 関数の引数としては動作しない、とか一貫性が無さ杉。
CSV吐かせるときに良く使うけど こんな感じ。 while (hogehoge) { //略 do { fst << *itr ; } while ( ++itr != max_itr , (fst << ", " , true) ); fst << endl; }
while (hogehoge) { //略 while(1){ fst << *itr ; if(++itr == max_itr) break; fst << ", "; } fst << endl; } の方がわかりやすいと思うが・・・
} while ( ++itr != max_itr && (fst << ", " , true) ); おもっきし間違えとるわorz
ループ終了・継続条件以外の処理をwhile(...)の中に含めるのはキモイ。
>>83 >でもそれカンマ演算子じゃないし。
???
>>89 変数・関数宣言ないのカンマは演算子ではない。
式中(もちろん関数呼び出し演算子内以外)でのカンマのみがカンマ演算子。
int a = (1,2);
switch(hoge) { case 1,2,3: ... } こんなコードをなんの警告も出さずにコンパイルしちゃう bcc 萌え。
>>92 それはそれでGCCの範囲指定ケース文みたいに振舞えばマンセーだが
foo(a,b,(c,d),(e,f));
>>93 bcc の場合、カンマ演算子の働きにより case 3: と等価なコードになる罠。
しかも、この罠、一度嵌ると問題の原因が恐ろしく分かり難く、えげつない。
BCCに限らずC/C++コンパイラなら全てそうだが。(警告はともかく)
>>96 はいはい、ちゃんと確認してから言いましょうね。
98 :
デフォルトの名無しさん :2005/08/07(日) 14:52:34
>>97 未確認ということにしておかないと、
何かあなたにとって都合が悪いのですか? :-)
2chネラは馬鹿だから取り合えず一言目は煽りなのですよ ;-D
>>96 ,
>>98 少なくとも vc, ic, gcc, mwcc ではあんなコードはエラーになる。
>>99 昔は俺もそう思ってたけど、他の板とか見てると
やっぱりプログラマって人格に問題がある人が多いみたい。
同じプログラマとして恥ずかしい限り。
・・・俺もあんまり人のことは言えんけど。orz
というか、bcc 以外にあんなコードを通すコンパイラってあんの?
ひとつでもあって、たまたまそれしか知らなくて
>>96 みたいなこと
言ったんならミジンコ程度には同情の余地があるけど、
そうじゃないならプログラマには不向きというより
>>96 はただの馬鹿。
古いARM日本語訳を見たら、caseには定数式を指定するようになっていて、 定数式にカンマ演算子を使用してはならない、と書いてあるけど これは今も変わってないですか?
>>105 アンタさぁ、技術的に言い返せないんだったら、せめて面白いことのひとつでも言ったらぁ?
定数式はカンマ演算子を含まないからエラー出すのが正解だよな。 しかし、今まで知らなかったよ。 他の言語とゴッチャになってうっかりってこともあり得るからなぁ。
>>106 そのレスは技術的だったり面白かったりするんですか?
しないなら絵に描いたような自爆ですね :-P
>>104 JIS X3010 : 2003 (所謂 C99) によると
「定数式は、代入、増分、減分、関数呼び出し又は
コンマ演算子を含んではならない。」
>>109 まともに言い返せないのだったら、せめて面白いことのひとつくらい
言ってみてはどうでしょうか? ;-)
>>110 へぇー
じゃ、こんなのもありなのか・・・
#define case case 0?
#define label 3
#define goto
int main(void)
{
int i = 3;
if (i == 2)
goto label;
switch (i) {
case 2:
label:
printf("i == 2 ???\n");
break;
default:
printf("i != 2 ???\n");
}
return 0;
}
case 2,3,4: って書かずに case 2: case 3: case 4: って書けばいいだけじゃんかよー。
case 2: case 3: case 4:
>>112 ワロスww・・・でも、仕事でこんなコード書いたら10回ヌッコロス!
>>113 全く至極その通りなんだけど、それ全然論点が違うからww
case 3-5,8: みたいに書きたいよな
そこでPascalですよ
for(i=-1;i++,i<N;)
for (i=-N; i++; i<N)
#define CASE break; case #define OR :case とかすれば CASE 2 OR 3 OR 4: と書けるって昔読んだ入門書に載ってた 著者は文法を変えるようなマクロは使うべきではないと言ってた でもswitchの元々の文法が凶悪だからこれぐらいは仕方がないとも言ってた でも著者自身は使わないと言ってた
>>121 全くお勧めしない。その著者は、「郷に入りては郷に従え」という言葉を噛み締めるべき。
その例でいえば、
break;
case 2: case 3: case 4:
と書く習慣をつければすむだけの話。
おい、どこに勧めた奴がいるンだ? それに、こういう場合は郷に従えなんて言わないよ。
マクロで俺様言語を作るのはやめてください・・・ でも俺も #define FOR( i , n ) for(int i; i<(n); ++i) とかやってました。 FOR(a,10) hoge(a); って書くだけで、 for(int a; a<10; ++a) hoge(a); ってなるから結構便利だったが・・・
それは何回まわるのか
そして FOR(a+b,10) hoge(a); と書いたら
そこでboost::lambdaですよ。 template <typename T> inline ForLoop(int n, T fn) { for (int i = 0; i < n; ++i) fn(i); } //使用例省略
#define FOR( i , n ) for(int i=0; i<(n); ++i) の間違いだな。
>>127 せめてintはやめて、templateで型とれ
マクロで俺言語作るのは反対だが、for_each()は好んで使う漏れ。 C++を5年やっている香具師に何故マクロはダメでtemplateはいいのか聞かれた。 ……困ったもんだ。
標準のブツを使うのと、いわゆる「俺言語」をこさえるのじゃ 天と地だしなぁ。
C言語のプログラマって結構躊躇無くマクロを使う香具師って多いよね。
template が無い分、逆にマクロを使わざるを得ない場面が多いってのもあるんだろうけど。
>>130 名前空間を汚す問題を教えてやれ。
・・・ちなみにハゲはリファクタリングツールの妨げになるとかで、マクロの存在そのものをC++から消しさりたいらしい。
ただ消してしまうと、タイプリストがえらい目に遭うな。
>>132 名前空間の問題だけじゃなくて、マクロで作った俺言語自体が結構脆弱だったりする
FOR(*a, n++)とか書いたらまずいがコンパイラが文句を言う保証がない
ほかにも
#define SWAP(T,x,y) do { T w = x; x = y; y = w; } while (0)
という有名なマクロがあるけどwを渡されたり*p++なんてのを渡されると困る
インライン関数が、それなりにインライン展開される今となっては、そういう関数をマクロで作るべきではないよね。 マクロっていうのは、関数にしにくいもの、 大量にコピペするとミスるようなもの、 そういうのに使えばいいと思います。
「そういう関数」がどういう関数を指してるのかまるでわからん
マクロはたまに includeファイルへの引数として使うな〜 undef使えば衝突の恐れないし。 templateとpolymorphicのパラメタライズだと 継承や仮想関数使うと遅くなりそうだし、 何より複雑な複数の関数の管理をするときが嫌。
>>137 >>135 の挙げている例の指しているんだろう。
そして恐らくは、「それに代表されるような、サイズの小さな関数に置き換えられる処理全般」
も、曖昧ながら対象に入れているのでは。
「置き換えられ」ないからこその俺言語なんだが。
>>135 は、「何故マクロはダメでtemplateはいいのか」
に対する答え(の一つ)のつもりで書いた。
templateなら同等の機能をもっと安全に実現できるってことをはっきり書かなかったのは悪かった
でもperformance hackのためのマクロの話なんて誰もしていない
>>140 だからさー、
>>136 は
そういう関数( do { T w = x; x = y; y = w; } while (0) )
をマクロで作る( SWAP(T,x,y) )
べきではないよねって言ってんの。
だから関数じゃない(関数に置き換えられない)って言ってるだろ
荒らしに反応したらあなたも荒らしかも。。。
135がなにを粘ってるのかわからん
ていうか、 ただ中カッコで囲むだけで変数のスコープを限定できるのに、 どーしてダミーのdo〜whileで囲むのか。 そんな糞なコンパイラは捨ててしまえ。
>>146 #include <iostream>
#define SWAP(T, x, y) {T tmp = x; x = y; y = tmp;}
int main(){
int a = 0; int b = 1;
if(false)
SWAP(int, a, b);
else
std::cout << "Hello, world!" << std::endl;
}
>>147 みたいなコーディングする糞プログラマも捨ててしまえ。
#include <iostream>
#define SWAP(T, x, y) {T tmp = x; x = y; y = tmp;}
int main(){
int a = 0; int b = 1;
if(false) {
SWAP(int, a, b);
} else {
std::cout << "Hello, world!" << std::endl;
}
}
というふうに書くのが普通。
ifで{}を省いていいのは、
if (hoge) foobar ;
など、一行で書くようなシンプルなものだけだ。
>>149 自分以外に使われる可能性があれば、念のためにもdo { } while (0)を書いておいて損はないだろ。
ところでCならともかく、C++なら<algorithm>にstd::swapがある。
俺の場合はどんなにシンプルでも絶対に if で { } は省かんけどなぁ。 あと、そもそも do { 〜 } while(0) バージョンの SWAP でも hoge() && SWAP(int, a, b); みたいな使い方とかできないんだし、どの道五十歩百歩だと思う。
>>151 その前にもしSWAPが値を返すとしたら、お前は一体何を返すことを期待するのか?
>>152 必ずしも SWAP が値を返す必要はない。
hoge() && (SWAP(int, a, b), 0)
154 :
デフォルトの名無しさん :2005/09/15(木) 01:14:07
>>149 が作ったライブラリは死んでも使いたくないな。
バグがあっても一般的でない使い方をする方が悪いと逆切れされそうだ。
>>154 ドキュメントにそういう使い方をするなと書かれてさえいれば、それはバグではなく仕様。
あと、俺だったら死ぬよりは使うほうを選ぶ。命をそんなことで粗末にするな。
>>153 みたいな使い方はトリックでしかないと思うが、
while文でカンマ演算子を使いたくなることは多々あるね。
158 :
デフォルトの名無しさん :2005/09/15(木) 01:55:45
>>156 「糞仕様」なライブラリは使いたくないって話だろ。「仕様」と書けばなんでも許されると思ってるのか?
>>158 許されるかどうかという問題と、バグか否かはまた別の問題。
仕様だと書かれていれば少なくともバグではない。
>>147 みたいな書き方こそが、バグが出やすいわけですが。
>>161 流れ読んでるのか?
>>147 の
「#define SWAP(T, x, y) {T tmp = x; x = y; y = tmp;}」
が問題って話だよ。
>>160 要求仕様にない想定していない使われ方をすれば問題が起きやすくても当たり前。
>>163 普通なら安全と思われても仕方ない記述を禁じる仕様ってのはどうなんだろう。
どうしてもコーディングスタイルを縛らなければならないほどの捨てがたい
トレードオフがあるなら、それに従おうというものだが、今回のケースはどうよ?
>>165 誰もそのマクロにバグがあるとは言ってないだろ
「仕様」だと主張することは「許される」ことと同義だと思うが。
166=168 なら矛盾したことを言ってるぞ。
>>170 定義1:仕様であるならバグではない。(
>>159 )
定義2:誰もバグがあるとは言っていない(
>>166 )
定義3:仕様であれば許される。(
>>168 )
定義1と定義3から「バグがあるから許されない」となるが、定義2と矛盾する。
ただし、166=168が定義1そのものを否定するならば矛盾はしていない。
しかし、定義1はバグの定義として一般的に広く浸透している考えなので、
166=168が定義1を否定していないものと仮定した。
定義2は完全に肯定する。(俺自身の言葉だし)
定義1は肯定するが今回の話とは無関係。
>>160 は俺。
なんで定義1と定義3から「バグがあるから」の言葉が出てくるのかわからん。
インライン関数にすりゃいいものを、どーしてマクロでやりたがるの? 同じことを実現する2つのやり方があった場合、 より良い方を選ばないのは、どうしてだい?
Cだから。
>>173 Cには参照渡しがないから関数でやろうとするとポインタ渡しになる。
俺はそれでもインライン関数にするけどな。
俺はC++の参照渡しを安易に使うのには反対だ。constを適切に使えばいい、という人もいるけどさ。 CFoo oFoo ; hogehoge(oFoo) ; とやった場合に、呼んだ側からは、実体渡しなのか参照渡しなのか、わからないのだ。
>>174 よりよいCとしてC++を使えない、
純粋なCで書かないといけない、という制限があるなら、しかたないね。
>>176 わからなくさせるための参照渡しですから。
参照か否かではなく、変更されるのかされないのかが問題
だからconstを適切に使えばいい 代入演算子をオーバーロードするときは参照をconstなしで渡すけどね
関数の引数にするときは必ずconst_cast<const T>せよということですか
そこでboost::crefですよ
>>181 まともなライブラリを使えということです。
今時のまともなC/C++ライブラリは変更しない引数にはconstがついてますから。
まともじゃないライブラリを使ってる場合はinline関数でラッパーライブラリでもいいです。
醜いconst_castが一箇所に収まりますから。
template みたいな大きな機能だけでなくカンマやら const やらの小ネタで独立したスレが立ってしまうのもC++ならではだよなぁ。
よし、おれいまから"register指定詞だけでギャルにモテモテになるスレ"立ててくる!!
∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵。∴∵ ∴∵∴∵:。∴∵∴∵∴: --─- ∴∵∴∵∴∵∴∵ ∴∵゜∴∵∴∵∴∵ (___ )(___ ) ∴∵。∴∵∴∵ ゜ ∴∵∴∵∴:∵∴∵_ i/ = =ヽi ∴∵∴∵。∴∵∴ ∴∵☆彡∴∵∵ //[|| 」 ||] ∵∵∵∵∴:∵∴∵ ∴∵∴∵∴∵ / ヘ | | ____,ヽ | | ∴:∵∴∵∴∵:∴∵ ∴゚∴∵∴∵ /ヽ ノ ヽ__./ ∴∵∴∵:∴∵∴∵ ∴∵∴∵ く / 三三三∠⌒> ∴:∵∴∵:∴∵ ∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵∵∴∵∴∵ ∧∧ ∧∧ ∧∧ ∧∧ ( )ゝ ( )ゝ( )ゝ( )ゝ ムチャシヤガッテ・・・ i⌒ / i⌒ / i⌒ / i⌒ / 三 | 三 | 三 | 三 | ∪ ∪ ∪ ∪ ∪ ∪ ∪ ∪ 三三 三三 三三 三三
>>183 呼び出しているところだけを見ても、変更される可能性があるかどうか
わからないという話なので、関数がどう宣言されているかは関係ないと思います!
constじゃない参照は使わないというポリシーじゃないと、これの解決策に
なりません!
> constじゃない参照は使わないというポリシー それが良識です。
というか常識です。
参照は言語仕様からはずしてconst指定すると自動的に参照渡しになるように変更でFA
>>192 operator [] () とかを実装できなくなるからダメ。てか、カンマの話をしようぜ。
194 :
デフォルトの名無しさん :2005/09/17(土) 11:59:45
out引数かどうかなんてのは結局ポインタ値渡しだったとしても関数呼び出し見ただけでは判らないんじゃないのか?
ちょっと前のBlitz++ライブラリでは、カンマ演算子が配列への代入に使われていた。 初めて見たときはちょっと感心した。
>>195 >>15 , 25
ていうかlistとvectorで定義を分ける必要はないんだが
>>25 set, hash_set等でも同じことができるように container_traitsがホスィ
昔、計算とリターンを一行でやりたくて、 return a+=b, b; って書いたら、bが返却された覚えがあるんだけど これって正しい記述方法なの?
カンマ演算子について調べろ。
>>194 とりあえずC言語時代には、
int n ;
foo(n) ;
bar(&n) ;
とあったら、fooはinでbarはoutだよね。
その慣習からすれば、
constの参照で渡す場合はin、ポインタで渡す場合はout、というのが自然じゃないか?
多値をカンマで返す処理系(perlやluaなど)はカンマ演算子ないよな
LISPなら prognがカンマ演算子に近いかな。 (progn 式1 式2 … 式n) 式1 から式n を順に評価して式nの値を返す。
するとCは複文を式中に書けないのが原因だな GCCではできるんだが
>>199 const * でもない限りは in/outかoutとは考えても out onlyとは先ず想定しないだろ。
foo(int &n)の場合、inの見た目を持ったoutかも知れない、というのはあるが、それはbar(int *n)だって同じこと。
引数でデータ返そうとする時点で紛らわしくなるのはもう仕方のないことだろう。
空気読めてないのは君だよ…。
>>200 カンマに2通りの意味があったらややこしいもんな
何かわかりやすい違い(関数呼び出しとそれ以外、とか)があれば別だが
Schemeの場合
カンマ演算子的なもの:(begin 1 2 3)
多値:(values 1 2 3)
まあ元々プロシージャの中に式は並べて書けるんだが
つーかCの引数の区切りも無理にカンマにせんで良かったんでは。 いや、今更変えられたら困るが。
>>207 それを言うなら、カンマ演算子に他の記号を使ってもよかったんでは?
てか、そもそもC的にカンマ演算子の必要性が見出せんのだが・・・
C++なら多少はカンマ演算子があるおかげで楽をできる場面があるから
わからんでもないんだが。
returnやgotoが「文」なのがいけないと思う throwは「式」なのに・・ いっそのこと全部式にしてしまって、return文廃止にしたらどうだろうか。 ・・まあ妄想はここまでにしておこう。
return は文のままでも、 return (a) ; とかって書けるじゃないか。 関数の引き数だって、foo( (a, b, c), d) とか書けるんじゃないか?
そんなのわかってるよ^^ だから何?^^
>>209 return式の評価中にreturn式やgoto式が出たときの動作をどうするんだろ・・・
return flg ? (return a) : (goto lbl) みたいな奴
>>212 throwの結果の型は確かvoidだったと思う。
それと同じようにreturnやgotoも結果の型をvoidにしてしまえばいい。
>>214 ああそうか。C++はreturn void;を許していたんだな。最初これを見たときは
( Д ) 彡 ゜ ゜ポカーンだったが。