【C】カンマ演算子を極めるスレ【C++】

このエントリーをはてなブックマークに追加
1デフォルトの名無しさん
,,,,,,,,,,,,,,,,,,の使い方を極めよう。
漢なら。
2デフォルトの名無しさん:2005/03/28(月) 21:14:40
えぴすてーめー氏の記事でなんかみたことあるな
おー、こういう使い方もできるのかと
( ・∀・)つ〃∩ 80ヘェくらい
3デフォルトの名無しさん:2005/03/28(月) 21:57:02
なにそれ
4デフォルトの名無しさん:2005/03/28(月) 22:02:31
カンマを極めたら何が出来るようになるんだ?
5デフォルトの名無しさん:2005/03/28(月) 22:05:30
常に exp2 の値を返します。ただし、代入演算子(=など)よりも優先度が低いため、xx = 1, 2; は (xx = 1), 2; と解釈されるので注意してください。また、関数の引数にカンマ(,)を用いた場合は、カンマ演算子とは解釈されません。

for (i = 0, j = 0; i < 10; i++) {
:
}

6デフォルトの名無しさん:2005/03/28(月) 22:06:14
カンマ演算子を使うと、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 が0になることを利用している所がポイントです。しかし、見てすぐ分かるように、一つの式の中に副作用が複数回あり、従って、この結果は未定義となります。
 次のようにカンマで区切って書くと、副作用の影響は消滅します。なぜなら、カンマ演算子は、左から右に評価すると仕様で決められているからです。

a ^= b, b ^= a, a ^= b

 しかし、これでもなお、このコードは同一のオブジェクトに対して動作しない (aとaを交換するとどんな値になるか?)という欠点があるため、実際にプログラムに使うのは止めておいた方が無難でしょう。
8デフォルトの名無しさん:2005/03/28(月) 22:17:10
Q 【&&や||と副作用完了点】
 && や || を使ったコードの中には、評価順序が左から右という前提で書かれているものがあるが、
評価順序は不定ではないのか。

 例外として、評価順序が決まっている演算子があります。 && 、 || 、
カンマ演算子の「 , 」、三項演算子の「 :? 」です。これらは、左を評価し、
その後に右が評価されることになります。
 ある時点においてそこまでの副作用が全て完了することが保証されている
区切りのことを、副作用完了点(sequence point)と呼びます。前述の演算子は、
左の式を評価した直後が副作用完了点となっています。
つまり、左が処理し終わってから右が処理されることが保証されているわけです。

 なお、関数の引数を区切るのに使うカンマは、カンマ演算子ではないため、
評価順序は不定です。
9デフォルトの名無しさん:2005/03/28(月) 22:19:09
でも自分でoperator || とか定義しちゃったら、順番の保障はなくなるよね?
10デフォルトの名無しさん:2005/03/28(月) 22:20:17
さらにカンマ演算子もオーバーロードできる罠。
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
>カンマ演算子もオーバーロードできる罠。
しらんかった。
13デフォルトの名無しさん:2005/03/28(月) 22:39:18
ttp://www.cbook24.com/bm_detail.asp?sku=4797328541
>11.5.5 カンマ演算子のオーバロード
14デフォルトの名無しさん:2005/03/28(月) 22:47:11
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 型関数をコールしたい場合には、カンマ演算子で適当な値を返してやればよい。
15デフォルトの名無しさん:2005/03/28(月) 22:50:14
boost assign libraryのoperator+=の実装は面白かった。
vector<int> v;
v += 1, 2, 3, 4, 5, 6;
とか…
16デフォルトの名無しさん:2005/03/31(木) 15:22:28
>>6
>また、変数の宣言を、
>int i, j, k;
>のようにできますが、これもカンマ演算子の1つの使い方といえます。
(`・ω・´)
17デフォルトの名無しさん:皇紀2665/04/01(金) 05:24:37
で、char* a, b, cと書いてハマると。
18デフォルトの名無しさん:皇紀2665/04/01(金) 05:34:08
>>17
馬鹿対策のために、そういう変数宣言は禁止されてるな。

typedefしててもダメなんだよな、馬鹿がそれ見て
char* a, b, c ;
なんて書いたりするから、そういう書き方ができることすら、知られないようにする必要がある。
19デフォルトの名無しさん:皇紀2665/04/01(金) 07:46:44
16が言ってるのはそういうことじゃなくて
int i,j,k;のカンマは演算子じゃないってことだと思うが
20デフォルトの名無しさん:2005/04/09(土) 01:25:17
2665年?皇紀?
21デフォルトの名無しさん:2005/04/09(土) 22:19:07
エイプリルフールで日付が変わっただけ。
格闘技板ではホースト生誕40年とか
自作板ではAMD暦とか、色々あった。
22デフォルトの名無しさん:2005/04/10(日) 09:47:38
マクロに複数の式や関数を書くときにも役に立つ。

それがカンマ演算師。
23デフォルトの名無しさん:2005/04/10(日) 09:50:01
24デフォルトの名無しさん:2005/04/13(水) 14:11:45
>>14
log4c 使えば?
25デフォルトの名無しさん:2005/05/20(金) 12:02:22
ちょっとした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));


26デフォルトの名無しさん:2005/05/24(火) 02:41:41
>25
list<int> l = list<int>(), 1, 2, 3, 4, 5;
27デフォルトの名無しさん:2005/05/24(火) 06:10:11
まんまBoost Assignment Libraryじゃないか
28デフォルトの名無しさん:2005/05/24(火) 20:06:30
boostとか見てると、もうアホかと。
C++自体の言語仕様を拡張したほうがいいのに、
STL作った連中はトリッキーな手法で問題を解決しようとしてる。

そりゃ言語仕様を拡張したらコンパイラにも手を入れる必要が出てしまう。
世の中の数多くのコンパイラに変更を強いるよりも、
コンパイラは変えないで済むなら変えないほうがいいという考え方もあるだろう。

でも思い出してくれ。
C++は当初コンパイラはなく、
C++のソースからCのソースを出力するトランスレータで実現されていたことを。

C++の範囲内で工夫するよりも、
C++を拡張したC++++という言語を作って、
C++++のソース化らC++のソースを出力するトランスレータを使えばいいんだよ。
29デフォルトの名無しさん:2005/05/24(火) 21:58:51
>>28
ソレダ
30デフォルトの名無しさん:2005/05/24(火) 22:32:59
最終的に+いくつ付くんだ
31デフォルトの名無しさん:2005/05/25(水) 15:58:16
>>28>>30
C# って、漏れの目には
++
++
に見える。+がよっつついたのがC#なんだよ。
32デフォルトの名無しさん:2005/05/25(水) 22:26:40
 ┼

こう斜めに重なって # になったというのを、
タバコ屋のおばちゃんから聞いたことがある。
33デフォルトの名無しさん:2005/05/26(木) 07:47:00
音楽の記号で半音上げる意味から来てんのかと思ってた
34デフォルトの名無しさん:2005/05/26(木) 17:02:05
>>33
ならば#ではなく♯と表記せねば。

…だが7bit系では無理。
35デフォルトの名無しさん:2005/05/26(木) 21:10:48
JIS
36デフォルトの名無しさん:2005/05/27(金) 10:26:49
UTF-7
37デフォルトの名無しさん:2005/05/28(土) 16:10:50
C#って読みはシーシャープなのに表記はC#が正しいんだよな。
この板見てたらC♯って表記が目立つけど。
38デフォルトの名無しさん:2005/05/28(土) 16:16:10
全角文字の方が正しいのか?
39デフォルトの名無しさん:2005/05/28(土) 16:54:34
C♯も全角文字だが?
40デフォルトの名無しさん:2005/05/28(土) 18:19:17
そうじゃねーよ。
外人が作ったのに、全角表記が正しいのかってことだよ。
41デフォルトの名無しさん:2005/05/28(土) 18:42:00
>外人が作ったのに、全角表記が正しいのかってことだよ。
>外人が作ったのに、全角表記が正しいのかってことだよ。
>外人が作ったのに、全角表記が正しいのかってことだよ。
>外人が作ったのに、全角表記が正しいのかってことだよ。
>外人が作ったのに、全角表記が正しいのかってことだよ。
42デフォルトの名無しさん:2005/05/28(土) 19:00:03
43デフォルトの名無しさん:2005/05/28(土) 19:21:17
44デフォルトの名無しさん:2005/05/28(土) 19:25:32
>>40
まっとすみって何ですか?
45デフォルトの名無しさん:2005/05/28(土) 23:32:15
C#

2文字とも半角ですが何か。
46デフォルトの名無しさん:2005/05/29(日) 05:46:27
井桁だって、慣例的にシャープと読んできたやん
それでEやん
47デフォルトの名無しさん:2005/05/30(月) 22:35:05
>>46
そうかい?
俺はシャープと読むのは恥ずかしいからよしておけと
言われてたが。
C#が出るまでの話だがな……。
48デフォルトの名無しさん:2005/06/01(水) 12:45:35
つまり「#をシャープと読むのは恥ずかしいからよしておけ」と公言してた香具師のほうが
恥かしい香具師だったってことだな。
49デフォルトの名無しさん:2005/06/02(木) 06:51:15
#をシャープと読むのはいいけど、#をシャープと読むのは如何なものかと思う。
シャープは♯だ。
50デフォルトの名無しさん:2005/06/06(月) 17:00:41
確かにシャープは♯だ
でもシーシャープはC♯ではなく、C#だ
51デフォルトの名無しさん:2005/06/06(月) 22:21:09
C井を
52デフォルトの名無しさん:2005/06/06(月) 23:14:48
C丼
53デフォルトの名無しさん:2005/06/08(水) 20:56:30
だーかーらー、全角で書くな。
54デフォルトの名無しさん:2005/06/08(水) 22:34:43
C‡‡
55デフォルトの名無しさん:2005/06/11(土) 18:39:07
>>53
どっちでも良いんだよ。
56デフォルトの名無しさん:2005/07/06(水) 12:56:11
で、カンマはどこいったんだ?
57デフォルトの名無しさん:2005/07/06(水) 20:15:47
>>55
普通は外人が読めなくなる
どっちでもいいとか言ってる奴に限って
デフォルトエンコードがSJISだったりして
58デフォルトの名無しさん:2005/07/08(金) 18:00:37
>>57
日本語で何いってるんだ? おまえ
59デフォルトの名無しさん:2005/07/08(金) 19:28:34
日本語を読めるのは日本人だけなのか?
60デフォルトの名無しさん:2005/07/08(金) 19:32:08
つーか
ここに日本語で書くのと、C#を全角で書くかどうかは別問題だろ
しかもスレ違い
61デフォルトの名無しさん:2005/07/08(金) 21:07:00
シーシャープって読まなかったら シー井桁とでもよむんですかい?
62デフォルトの名無しさん:2005/07/09(土) 15:19:40
>>60
>>55は「外人が読めなくなる」としか言ってないんだが、何が別問題だ?
日本語が読める環境ならどっちでもいいだろうし、C#が読めないような環境なら日本語も読めない。
完全に同じ問題だ。

大体C#の日本語の正式名称は「プログラム言語C#」で、C#とは書いてない
ま、「表記」はロゴじゃないんだし全角か半角かなんて話は関係ないがな。
63デフォルトの名無しさん:2005/07/09(土) 20:29:02
while ((a = func(...)) != hogegege) { ... }
みたいな書き方ってよくするけど

while (a = func(...), a != hogegege) { ... }
ってした方が読みやすくね?



aを2回書くのが面倒か、そうか。
64デフォルトの名無しさん:2005/07/09(土) 21:18:54
>>63
読みやすくないよ。
65デフォルトの名無しさん:2005/07/09(土) 22:01:13
>>64
そう?
じゃ、やめるわ。
66デフォルトの名無しさん:2005/07/09(土) 22:03:41
>>65
音読してみることをお勧め。
・funcを呼び出した結果をaに入れ、その値がhogegegeじゃなかったら
・funcを呼び出した結果をaに入れ、aがhogegegeじゃなかったら
#あ、大差ないじゃんw
67デフォルトの名無しさん:2005/07/09(土) 22:53:17
>>66
まぁこういうのは人によるんだろうけど、俺の場合は
上だといきなり「funcの戻り値とhoghogeの比較」という思考に至れるのに対して、
下だとhogehogeの比較の時に、ほんの一瞬、マジで一瞬のことだけど、
「aって何だっけ? ああそうだfuncの戻り値だ」
という余分な思考コストがかかるな。
6866:2005/07/09(土) 23:07:21
>>67
判ります。>66ではわざと大差ないと書いたけど、その僅かな違いが余計な思考コストになるんですよね。
69デフォルトの名無しさん:2005/07/10(日) 08:25:16
漏れは一瞬だけ、
funcの返り値をaに代入できたかどうかを評価してその真偽とhogehogeが一致しなければ
に見える。

真偽を==や!=で比較しちゃいけないから、そもそもそんな読み方はありえないけど。
70デフォルトの名無しさん:2005/07/10(日) 20:21:40
夜中にこっそり
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());
見たいにカンマ区切りで変数を複数宣言する事が出来ねぇだ。
何でこんな仕様なんだろ?
72ビル・ジョブス:2005/08/04(木) 14:59:06
そこでは式は許されるが、宣言しちゃいけないからだよ。
そのローカル変数のスコープはどうなる?
73デフォルトの名無しさん:2005/08/04(木) 15:30:09
>>71
そういやなんで for だけは許されてるんだろうな。
74デフォルトの名無しさん:2005/08/04(木) 15:32:32
whileとの差別化。
75デフォルトの名無しさん:2005/08/04(木) 15:52:38
>>72
複数できないだけで宣言そのものは出来るよ。
if(int value = 0)
{
   変数のスコープ
}
見たいに。
76デフォルトの名無しさん:2005/08/04(木) 16:40:26
>>75
知らなかった。
そんなこと出来るんだ。

でもforだと
for (inti i=0; i<100; i++) hoge(i);
の後もiが生きててなんか気持ち悪い。
vc++のデバッグモードでみてるとiが沢山いるんだょ。
c風に先頭で宣言して使いまわすべきなのか。
77デフォルトの名無しさん:2005/08/04(木) 17:00:38
>>76
それはVC6が古い所為。
VC7.1なら今の言語仕様通りfor文の外では無効になる。
#ただし、互換性のためにオプションで切り替えることになる。
78デフォルトの名無しさん:2005/08/04(木) 19:04:38
>>76
Condition変数というそうな。
79デフォルトの名無しさん:2005/08/04(木) 19:04:39
>>76
#define for if (0) else forってやると現行の仕様どおりのスコープになる。
80デフォルトの名無しさん:2005/08/04(木) 19:55:34
特に意味ないがコンマでこんな事も出来る。
 if(int value = func(value)) int a = value,b = func(a),func2(int),(*pfunc)(int) = func2,c = pfunc(b);
By BCC
最後のcの位置だけはどうしても用途が無い。
なんか用途あったらキボンヌ。
81デフォルトの名無しさん:2005/08/04(木) 22:48:10
個人的にはスコープは{}と対応していないと気持ち悪いな。
{ int i ; for(;;){}} でいいじゃないか。
82デフォルトの名無しさん:2005/08/06(土) 12:22:33
関数はいいのか
83デフォルトの名無しさん:2005/08/06(土) 12:40:15
>>80
でもそれカンマ演算子じゃないし。
84デフォルトの名無しさん:2005/08/06(土) 18:29:07
カンマ演算子って、for文の更新条件を複数書くために苦し紛れに導入したって感じがして好かない。
関数の引数としては動作しない、とか一貫性が無さ杉。
85デフォルトの名無しさん:2005/08/06(土) 18:35:39
CSV吐かせるときに良く使うけど
こんな感じ。

while (hogehoge) {
//略
do {
fst << *itr ;
} while ( ++itr != max_itr , (fst << ", " , true) );
fst << endl;
}
86デフォルトの名無しさん:2005/08/06(土) 18:50:44
while (hogehoge) {
//略
while(1){
fst << *itr ;
if(++itr == max_itr) break;
fst << ", ";
}
fst << endl;
}

の方がわかりやすいと思うが・・・
87デフォルトの名無しさん:2005/08/06(土) 18:53:45
} while ( ++itr != max_itr && (fst << ", " , true) );

おもっきし間違えとるわorz
88デフォルトの名無しさん:2005/08/06(土) 19:11:56
ループ終了・継続条件以外の処理をwhile(...)の中に含めるのはキモイ。
89デフォルトの名無しさん:2005/08/06(土) 21:50:09
>>83
>でもそれカンマ演算子じゃないし。

???
90デフォルトの名無しさん:2005/08/06(土) 22:35:52
>>89
変数・関数宣言ないのカンマは演算子ではない。
式中(もちろん関数呼び出し演算子内以外)でのカンマのみがカンマ演算子。
91デフォルトの名無しさん:2005/08/07(日) 02:33:20
int a = (1,2);
92デフォルトの名無しさん:2005/08/07(日) 03:38:38
switch(hoge) {
  case 1,2,3:
    ...
}

こんなコードをなんの警告も出さずにコンパイルしちゃう bcc 萌え。
93デフォルトの名無しさん:2005/08/07(日) 03:40:38
>>92
それはそれでGCCの範囲指定ケース文みたいに振舞えばマンセーだが
94デフォルトの名無しさん:2005/08/07(日) 03:44:41
foo(a,b,(c,d),(e,f));
95デフォルトの名無しさん:2005/08/07(日) 04:28:02
>>93
bcc の場合、カンマ演算子の働きにより case 3: と等価なコードになる罠。
しかも、この罠、一度嵌ると問題の原因が恐ろしく分かり難く、えげつない。
96デフォルトの名無しさん:2005/08/07(日) 09:21:16
BCCに限らずC/C++コンパイラなら全てそうだが。(警告はともかく)
97デフォルトの名無しさん:2005/08/07(日) 14:27:44
>>96
はいはい、ちゃんと確認してから言いましょうね。
98デフォルトの名無しさん:2005/08/07(日) 14:52:34
>>97
未確認ということにしておかないと、
何かあなたにとって都合が悪いのですか? :-)
99マイク ◆yrBrqfF1Ew :2005/08/07(日) 15:15:43
2chネラは馬鹿だから取り合えず一言目は煽りなのですよ ;-D
100デフォルトの名無しさん:2005/08/07(日) 15:42:57
>>96,>>98
少なくとも vc, ic, gcc, mwcc ではあんなコードはエラーになる。

>>99
昔は俺もそう思ってたけど、他の板とか見てると
やっぱりプログラマって人格に問題がある人が多いみたい。
同じプログラマとして恥ずかしい限り。




・・・俺もあんまり人のことは言えんけど。orz
101デフォルトの名無しさん:2005/08/07(日) 16:14:11
単に>>100の人格に問題があるだけだと思う
102デフォルトの名無しさん:2005/08/07(日) 20:47:28
全てと言い切る>>96はプログラマに不向きだ。
103デフォルトの名無しさん:2005/08/07(日) 20:51:20
というか、bcc 以外にあんなコードを通すコンパイラってあんの?
ひとつでもあって、たまたまそれしか知らなくて >>96 みたいなこと
言ったんならミジンコ程度には同情の余地があるけど、
そうじゃないならプログラマには不向きというより >>96 はただの馬鹿。
104デフォルトの名無しさん:2005/08/07(日) 21:43:06
古いARM日本語訳を見たら、caseには定数式を指定するようになっていて、
定数式にカンマ演算子を使用してはならない、と書いてあるけど
これは今も変わってないですか?
105デフォルトの名無しさん:2005/08/07(日) 22:55:45
>>103
ミジンコって昭和のセンスですよ。
106デフォルトの名無しさん:2005/08/08(月) 06:24:18
>>105
アンタさぁ、技術的に言い返せないんだったら、せめて面白いことのひとつでも言ったらぁ?
107デフォルトの名無しさん:2005/08/08(月) 07:04:29
定数式はカンマ演算子を含まないからエラー出すのが正解だよな。
しかし、今まで知らなかったよ。
他の言語とゴッチャになってうっかりってこともあり得るからなぁ。
108デフォルトの名無しさん:2005/08/08(月) 11:41:04
>>106
そのレスは技術的だったり面白かったりするんですか?
しないなら絵に描いたような自爆ですね :-P
109デフォルトの名無しさん:2005/08/09(火) 12:55:05
>>108
もう巣に帰れ。
110デフォルトの名無しさん:2005/08/09(火) 13:05:41
>>104
JIS X3010 : 2003 (所謂 C99) によると
「定数式は、代入、増分、減分、関数呼び出し又は
コンマ演算子を含んではならない。」
111デフォルトの名無しさん:2005/08/09(火) 16:34:02
>>109
まともに言い返せないのだったら、せめて面白いことのひとつくらい
言ってみてはどうでしょうか? ;-)
112デフォルトの名無しさん:2005/08/09(火) 22:50:32
>>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;
}
113デフォルトの名無しさん:2005/08/09(火) 23:16:13
case 2,3,4:
って書かずに
case 2:
case 3:
case 4:
って書けばいいだけじゃんかよー。
114デフォルトの名無しさん:2005/08/09(火) 23:29:22
case 2: case 3: case 4:
115デフォルトの名無しさん:2005/08/10(水) 00:38:56
>>112
ワロスww・・・でも、仕事でこんなコード書いたら10回ヌッコロス!
116デフォルトの名無しさん:2005/08/10(水) 00:40:33
>>113
全く至極その通りなんだけど、それ全然論点が違うからww
117デフォルトの名無しさん:2005/08/13(土) 23:45:34
case 3-5,8: みたいに書きたいよな
118デフォルトの名無しさん:2005/08/18(木) 11:00:00
そこでPascalですよ
119デフォルトの名無しさん:2005/09/06(火) 06:54:21
for(i=-1;i++,i<N;)
120デフォルトの名無しさん:2005/09/06(火) 23:45:50
for (i=-N; i++; i<N)
121デフォルトの名無しさん:2005/09/09(金) 18:12:19
#define CASE break; case
#define OR :case

とかすれば CASE 2 OR 3 OR 4:
と書けるって昔読んだ入門書に載ってた
著者は文法を変えるようなマクロは使うべきではないと言ってた
でもswitchの元々の文法が凶悪だからこれぐらいは仕方がないとも言ってた
でも著者自身は使わないと言ってた
122デフォルトの名無しさん:2005/09/09(金) 18:34:37
>>121
全くお勧めしない。その著者は、「郷に入りては郷に従え」という言葉を噛み締めるべき。
その例でいえば、
break;
case 2: case 3: case 4:
と書く習慣をつければすむだけの話。
123デフォルトの名無しさん:2005/09/09(金) 19:11:24
おい、どこに勧めた奴がいるンだ? それに、こういう場合は郷に従えなんて言わないよ。

124デフォルトの名無しさん:2005/09/10(土) 00:04:58
マクロで俺様言語を作るのはやめてください・・・

でも俺も

#define FOR( i , n ) for(int i; i<(n); ++i)

とかやってました。

FOR(a,10) hoge(a);

って書くだけで、

for(int a; a<10; ++a) hoge(a);

ってなるから結構便利だったが・・・
125デフォルトの名無しさん:2005/09/10(土) 00:15:48
それは何回まわるのか
126デフォルトの名無しさん:2005/09/10(土) 00:30:09
そして
FOR(a+b,10) hoge(a);
と書いたら
127デフォルトの名無しさん:2005/09/10(土) 00:36:55
そこでboost::lambdaですよ。
template <typename T>
inline ForLoop(int n, T fn)
{
  for (int i = 0; i < n; ++i)
    fn(i);
}
//使用例省略
128デフォルトの名無しさん:2005/09/10(土) 02:27:51
#define FOR( i , n ) for(int i=0; i<(n); ++i)
の間違いだな。
129デフォルトの名無しさん:2005/09/10(土) 05:45:09
>>127
せめてintはやめて、templateで型とれ
130デフォルトの名無しさん:2005/09/10(土) 09:37:17
マクロで俺言語作るのは反対だが、for_each()は好んで使う漏れ。
C++を5年やっている香具師に何故マクロはダメでtemplateはいいのか聞かれた。
……困ったもんだ。
131デフォルトの名無しさん:2005/09/10(土) 09:55:11
標準のブツを使うのと、いわゆる「俺言語」をこさえるのじゃ
天と地だしなぁ。
132名無しさん@そうだ選挙に行こう:2005/09/11(日) 03:31:28
C言語のプログラマって結構躊躇無くマクロを使う香具師って多いよね。
template が無い分、逆にマクロを使わざるを得ない場面が多いってのもあるんだろうけど。

>>130
名前空間を汚す問題を教えてやれ。



・・・ちなみにハゲはリファクタリングツールの妨げになるとかで、マクロの存在そのものをC++から消しさりたいらしい。
133名無しさん@そうだ選挙に行こう:2005/09/11(日) 07:49:27
ただ消してしまうと、タイプリストがえらい目に遭うな。
134名無しさん@そうだ選挙に行こう:2005/09/11(日) 14:27:53
>133
代わりにこれじゃダメですか?

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1603.pdf

まぁ,マクロがなくなってえらい目に遭うのはタイプリストに限りませんけれど.
135名無しさん@そうだ選挙に行こう:2005/09/11(日) 20:39:08
>>132
名前空間の問題だけじゃなくて、マクロで作った俺言語自体が結構脆弱だったりする
FOR(*a, n++)とか書いたらまずいがコンパイラが文句を言う保証がない
ほかにも
#define SWAP(T,x,y) do { T w = x; x = y; y = w; } while (0)
という有名なマクロがあるけどwを渡されたり*p++なんてのを渡されると困る
136名無しさん@そうだ選挙に行こう:2005/09/11(日) 22:34:27
インライン関数が、それなりにインライン展開される今となっては、そういう関数をマクロで作るべきではないよね。

マクロっていうのは、関数にしにくいもの、
大量にコピペするとミスるようなもの、
そういうのに使えばいいと思います。
137デフォルトの名無しさん:2005/09/13(火) 12:58:31
「そういう関数」がどういう関数を指してるのかまるでわからん
138デフォルトの名無しさん:2005/09/13(火) 13:33:39
マクロはたまに
includeファイルへの引数として使うな〜
undef使えば衝突の恐れないし。

templateとpolymorphicのパラメタライズだと
継承や仮想関数使うと遅くなりそうだし、
何より複雑な複数の関数の管理をするときが嫌。
139デフォルトの名無しさん:2005/09/13(火) 16:32:06
>>137
>>135の挙げている例の指しているんだろう。
そして恐らくは、「それに代表されるような、サイズの小さな関数に置き換えられる処理全般」
も、曖昧ながら対象に入れているのでは。
140135=137:2005/09/13(火) 23:33:45
「置き換えられ」ないからこその俺言語なんだが。
>>135は、「何故マクロはダメでtemplateはいいのか」
に対する答え(の一つ)のつもりで書いた。
templateなら同等の機能をもっと安全に実現できるってことをはっきり書かなかったのは悪かった

でもperformance hackのためのマクロの話なんて誰もしていない
141デフォルトの名無しさん:2005/09/14(水) 05:58:30
>>140
だからさー、>>136

そういう関数( do { T w = x; x = y; y = w; } while (0) )
をマクロで作る( SWAP(T,x,y) )

べきではないよねって言ってんの。
142デフォルトの名無しさん:2005/09/14(水) 10:46:51
だから関数じゃない(関数に置き換えられない)って言ってるだろ
143デフォルトの名無しさん:2005/09/14(水) 11:01:01
荒らしに反応したらあなたも荒らしかも。。。
144デフォルトの名無しさん:2005/09/14(水) 11:57:06
135がなにを粘ってるのかわからん
145デフォルトの名無しさん:2005/09/14(水) 17:15:21
>>136>>135をフォローしてるのに、どーして?
146デフォルトの名無しさん:2005/09/14(水) 17:16:35
ていうか、
ただ中カッコで囲むだけで変数のスコープを限定できるのに、
どーしてダミーのdo〜whileで囲むのか。

そんな糞なコンパイラは捨ててしまえ。

147デフォルトの名無しさん:2005/09/14(水) 18:52:38
>>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;
}
148デフォルトの名無しさん:2005/09/14(水) 18:53:08
http://www.bohyoh.com/CandCPP/FAQ/FAQ00008.html

ここはアホの子が多いのか?
149デフォルトの名無しさん:2005/09/14(水) 23:27:04
>>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 ;
など、一行で書くようなシンプルなものだけだ。
150デフォルトの名無しさん:2005/09/14(水) 23:35:10
>>149
自分以外に使われる可能性があれば、念のためにもdo { } while (0)を書いておいて損はないだろ。

ところでCならともかく、C++なら<algorithm>にstd::swapがある。
151デフォルトの名無しさん:2005/09/14(水) 23:37:58
俺の場合はどんなにシンプルでも絶対に if で { } は省かんけどなぁ。
あと、そもそも do { 〜 } while(0) バージョンの SWAP でも

    hoge() && SWAP(int, a, b);

みたいな使い方とかできないんだし、どの道五十歩百歩だと思う。
152デフォルトの名無しさん:2005/09/15(木) 00:01:34
>>151
その前にもしSWAPが値を返すとしたら、お前は一体何を返すことを期待するのか?
153デフォルトの名無しさん:2005/09/15(木) 00:05:46
>>152
必ずしも SWAP が値を返す必要はない。

    hoge() && (SWAP(int, a, b), 0)
154デフォルトの名無しさん:2005/09/15(木) 01:14:07
>>149 が作ったライブラリは死んでも使いたくないな。

バグがあっても一般的でない使い方をする方が悪いと逆切れされそうだ。
155デフォルトの名無しさん:2005/09/15(木) 01:21:49
>>153
珍しく、スレタイに沿った内容ですね。
156デフォルトの名無しさん:2005/09/15(木) 01:26:14
>>154
ドキュメントにそういう使い方をするなと書かれてさえいれば、それはバグではなく仕様。
あと、俺だったら死ぬよりは使うほうを選ぶ。命をそんなことで粗末にするな。
157デフォルトの名無しさん:2005/09/15(木) 01:38:00
>>153
みたいな使い方はトリックでしかないと思うが、
while文でカンマ演算子を使いたくなることは多々あるね。
158デフォルトの名無しさん:2005/09/15(木) 01:55:45
>>156
「糞仕様」なライブラリは使いたくないって話だろ。「仕様」と書けばなんでも許されると思ってるのか?
159デフォルトの名無しさん:2005/09/15(木) 02:17:48
>>158
許されるかどうかという問題と、バグか否かはまた別の問題。
仕様だと書かれていれば少なくともバグではない。
160デフォルトの名無しさん:2005/09/15(木) 02:21:11
>>159
バグが出やすいことに変わりは無い
161デフォルトの名無しさん:2005/09/15(木) 02:24:28
>>147みたいな書き方こそが、バグが出やすいわけですが。
162デフォルトの名無しさん:2005/09/15(木) 02:28:37
>>161
流れ読んでるのか?>>147
「#define SWAP(T, x, y) {T tmp = x; x = y; y = tmp;}」
が問題って話だよ。
163デフォルトの名無しさん:2005/09/15(木) 02:33:30
>>160
要求仕様にない想定していない使われ方をすれば問題が起きやすくても当たり前。
164デフォルトの名無しさん:2005/09/15(木) 02:47:31
>>163
普通なら安全と思われても仕方ない記述を禁じる仕様ってのはどうなんだろう。
どうしてもコーディングスタイルを縛らなければならないほどの捨てがたい
トレードオフがあるなら、それに従おうというものだが、今回のケースはどうよ?
165デフォルトの名無しさん:2005/09/15(木) 02:50:56
166デフォルトの名無しさん:2005/09/15(木) 03:01:58
>>165
誰もそのマクロにバグがあるとは言ってないだろ
167デフォルトの名無しさん:2005/09/15(木) 03:06:41
>>166
誰も許されるとは言ってないだろ
168デフォルトの名無しさん:2005/09/15(木) 03:14:25
「仕様」だと主張することは「許される」ことと同義だと思うが。
169デフォルトの名無しさん:2005/09/15(木) 03:20:23
166=168 なら矛盾したことを言ってるぞ。
170デフォルトの名無しさん:2005/09/15(木) 03:26:43
>>169
説明キボン
171デフォルトの名無しさん:2005/09/15(木) 03:39:38
>>170
定義1:仕様であるならバグではない。( >>159 )
定義2:誰もバグがあるとは言っていない( >>166 )
定義3:仕様であれば許される。( >>168 )

定義1と定義3から「バグがあるから許されない」となるが、定義2と矛盾する。

ただし、166=168が定義1そのものを否定するならば矛盾はしていない。
しかし、定義1はバグの定義として一般的に広く浸透している考えなので、
166=168が定義1を否定していないものと仮定した。
172デフォルトの名無しさん:2005/09/15(木) 03:55:47
定義2は完全に肯定する。(俺自身の言葉だし)
定義1は肯定するが今回の話とは無関係。>>160は俺。

なんで定義1と定義3から「バグがあるから」の言葉が出てくるのかわからん。
173デフォルトの名無しさん:2005/09/15(木) 19:37:36
インライン関数にすりゃいいものを、どーしてマクロでやりたがるの?

同じことを実現する2つのやり方があった場合、
より良い方を選ばないのは、どうしてだい?
174デフォルトの名無しさん:2005/09/15(木) 19:45:08
Cだから。
175デフォルトの名無しさん:2005/09/15(木) 21:53:25
>>173
Cには参照渡しがないから関数でやろうとするとポインタ渡しになる。
俺はそれでもインライン関数にするけどな。
176デフォルトの名無しさん:2005/09/15(木) 22:31:26
俺はC++の参照渡しを安易に使うのには反対だ。constを適切に使えばいい、という人もいるけどさ。

CFoo oFoo ;
hogehoge(oFoo) ;

とやった場合に、呼んだ側からは、実体渡しなのか参照渡しなのか、わからないのだ。
177デフォルトの名無しさん:2005/09/15(木) 22:32:26
>>174
よりよいCとしてC++を使えない、
純粋なCで書かないといけない、という制限があるなら、しかたないね。

178デフォルトの名無しさん:2005/09/15(木) 22:32:37
>>176
わからなくさせるための参照渡しですから。
179デフォルトの名無しさん:2005/09/15(木) 23:46:10
参照か否かではなく、変更されるのかされないのかが問題
180デフォルトの名無しさん:2005/09/15(木) 23:54:53
だからconstを適切に使えばいい
代入演算子をオーバーロードするときは参照をconstなしで渡すけどね
181デフォルトの名無しさん:2005/09/16(金) 00:00:20
関数の引数にするときは必ずconst_cast<const T>せよということですか
182デフォルトの名無しさん:2005/09/16(金) 00:07:46
そこでboost::crefですよ
183デフォルトの名無しさん:2005/09/17(土) 00:06:29
>>181
まともなライブラリを使えということです。
今時のまともなC/C++ライブラリは変更しない引数にはconstがついてますから。
まともじゃないライブラリを使ってる場合はinline関数でラッパーライブラリでもいいです。
醜いconst_castが一箇所に収まりますから。
184デフォルトの名無しさん:2005/09/17(土) 00:25:03
おまいら const の話ならこっちでしてくれ。過疎ってるんだ、頼む。

【C++】 const だけでメシが3杯食えちゃうスレ
http://pc8.2ch.net/test/read.cgi/tech/1078193971/
185デフォルトの名無しさん:2005/09/17(土) 00:47:05
186デフォルトの名無しさん:2005/09/17(土) 00:52:51
template みたいな大きな機能だけでなくカンマやら const やらの小ネタで独立したスレが立ってしまうのもC++ならではだよなぁ。
187ミノル小早川:2005/09/17(土) 01:13:27
よし、おれいまから"register指定詞だけでギャルにモテモテになるスレ"立ててくる!!
188デフォルトの名無しさん:2005/09/17(土) 01:24:21
∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵。∴∵
∴∵∴∵:。∴∵∴∵∴: --─- ∴∵∴∵∴∵∴∵
∴∵゜∴∵∴∵∴∵  (___ )(___ ) ∴∵。∴∵∴∵ ゜
∴∵∴∵∴:∵∴∵_ i/ = =ヽi ∴∵∴∵。∴∵∴
∴∵☆彡∴∵∵ //[||    」  ||] ∵∵∵∵∴:∵∴∵
∴∵∴∵∴∵ / ヘ | |  ____,ヽ | | ∴:∵∴∵∴∵:∴∵
∴゚∴∵∴∵ /ヽ ノ    ヽ__./  ∴∵∴∵:∴∵∴∵
∴∵∴∵  く  /     三三三∠⌒> ∴:∵∴∵:∴∵
∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵∴∵∵∴∵∴∵
   ∧∧   ∧∧  ∧∧   ∧∧
  (   )ゝ (   )ゝ(   )ゝ(   )ゝ ムチャシヤガッテ・・・
   i⌒ /   i⌒ /  i⌒ /   i⌒ /
   三  |  三  |  三  |  三  |
   ∪ ∪  ∪ ∪  ∪ ∪  ∪ ∪
  三三   三三  三三  三三
189デフォルトの名無しさん:2005/09/17(土) 02:07:36
>>183
呼び出しているところだけを見ても、変更される可能性があるかどうか
わからないという話なので、関数がどう宣言されているかは関係ないと思います!

constじゃない参照は使わないというポリシーじゃないと、これの解決策に
なりません!
190デフォルトの名無しさん:2005/09/17(土) 02:35:43
> constじゃない参照は使わないというポリシー

それが良識です。
191デフォルトの名無しさん:2005/09/17(土) 02:42:16
というか常識です。
192デフォルトの名無しさん:2005/09/17(土) 02:47:43
参照は言語仕様からはずしてconst指定すると自動的に参照渡しになるように変更でFA
193デフォルトの名無しさん:2005/09/17(土) 02:59:08
>>192
operator [] () とかを実装できなくなるからダメ。てか、カンマの話をしようぜ。
194デフォルトの名無しさん:2005/09/17(土) 11:59:45
out引数かどうかなんてのは結局ポインタ値渡しだったとしても関数呼び出し見ただけでは判らないんじゃないのか?
195デフォルトの名無しさん:2005/09/17(土) 13:19:21
ちょっと前のBlitz++ライブラリでは、カンマ演算子が配列への代入に使われていた。
初めて見たときはちょっと感心した。
196デフォルトの名無しさん:2005/09/17(土) 13:27:14
>>195
>>15, 25

ていうかlistとvectorで定義を分ける必要はないんだが>>25
set, hash_set等でも同じことができるように container_traitsがホスィ
197デフォルトの名無しさん:2005/09/17(土) 15:08:00
昔、計算とリターンを一行でやりたくて、

  return a+=b, b;

って書いたら、bが返却された覚えがあるんだけど
これって正しい記述方法なの?
198デフォルトの名無しさん:2005/09/17(土) 15:14:06
カンマ演算子について調べろ。
199デフォルトの名無しさん:2005/09/17(土) 16:42:23
>>194

とりあえずC言語時代には、
int n ;
foo(n) ;
bar(&n) ;
とあったら、fooはinでbarはoutだよね。

その慣習からすれば、
constの参照で渡す場合はin、ポインタで渡す場合はout、というのが自然じゃないか?
200デフォルトの名無しさん:2005/09/17(土) 17:00:00
多値をカンマで返す処理系(perlやluaなど)はカンマ演算子ないよな
201デフォルトの名無しさん:2005/09/17(土) 17:39:38
LISPなら prognがカンマ演算子に近いかな。

(progn 式1 式2 … 式n)
式1 から式n を順に評価して式nの値を返す。
202デフォルトの名無しさん:2005/09/17(土) 17:49:09
するとCは複文を式中に書けないのが原因だな
GCCではできるんだが
203デフォルトの名無しさん:2005/09/17(土) 20:27:10
>>199
const * でもない限りは in/outかoutとは考えても out onlyとは先ず想定しないだろ。
foo(int &n)の場合、inの見た目を持ったoutかも知れない、というのはあるが、それはbar(int *n)だって同じこと。
引数でデータ返そうとする時点で紛らわしくなるのはもう仕方のないことだろう。

204デフォルトの名無しさん:2005/09/17(土) 20:37:32
>>203
ちょっとはスレの前のほうを読もうぜ
>>176-191
205デフォルトの名無しさん:2005/09/17(土) 22:34:47
空気読めてないのは君だよ…。
206デフォルトの名無しさん:2005/09/17(土) 23:09:27
>>200
カンマに2通りの意味があったらややこしいもんな
何かわかりやすい違い(関数呼び出しとそれ以外、とか)があれば別だが

Schemeの場合
カンマ演算子的なもの:(begin 1 2 3)
多値:(values 1 2 3)

まあ元々プロシージャの中に式は並べて書けるんだが
207デフォルトの名無しさん:2005/09/18(日) 00:29:55
つーかCの引数の区切りも無理にカンマにせんで良かったんでは。
いや、今更変えられたら困るが。
208デフォルトの名無しさん:2005/09/18(日) 00:51:00
>>207
それを言うなら、カンマ演算子に他の記号を使ってもよかったんでは?
てか、そもそもC的にカンマ演算子の必要性が見出せんのだが・・・
C++なら多少はカンマ演算子があるおかげで楽をできる場面があるから
わからんでもないんだが。
209デフォルトの名無しさん:2005/09/18(日) 00:58:40
returnやgotoが「文」なのがいけないと思う
throwは「式」なのに・・
いっそのこと全部式にしてしまって、return文廃止にしたらどうだろうか。
・・まあ妄想はここまでにしておこう。
210デフォルトの名無しさん:2005/09/18(日) 01:04:05
return は文のままでも、
return (a) ;
とかって書けるじゃないか。

関数の引き数だって、foo( (a, b, c), d) とか書けるんじゃないか?
211デフォルトの名無しさん:2005/09/18(日) 01:06:09
そんなのわかってるよ^^
だから何?^^
212デフォルトの名無しさん:2005/09/18(日) 09:04:17
>>209
return式の評価中にreturn式やgoto式が出たときの動作をどうするんだろ・・・

return flg ? (return a) : (goto lbl) みたいな奴
213デフォルトの名無しさん:2005/09/18(日) 09:07:58
>>212
コンパイルしてみればわかる。
214デフォルトの名無しさん:2005/09/18(日) 21:17:06
>>212
throwの結果の型は確かvoidだったと思う。
それと同じようにreturnやgotoも結果の型をvoidにしてしまえばいい。
215デフォルトの名無しさん
>>214
ああそうか。C++はreturn void;を許していたんだな。最初これを見たときは
(  Д ) 彡 ゜ ゜ポカーンだったが。