久々のアリプラシリーズです。
こっ…これは…! コードから…深い味わいが伝わってくる… クソコードのはずなのに… な…何故だ!? このクソみたいな見た目に反した、爽やかな口当たり… そうだ…解ったぞ…桑の実(operator ,)だ! …小癪な真似を… このコードを書いた奴は誰だぁっ!!
— h.omae (@pigeon6) 2014, 3月 19
元のコードはc++なんですかね?と思って自分でコードを書いてみます。ええと、カンマ(コンマ)「,」演算子は、マクロでは使うけど演算子のオーバーロードをすると関数の引数とややこしくなるわけですが、「爽やかなコード」になるかどうかは分かりません。
確か、,演算子は優先度が一番低いから、そのあたりも含めて使うといいかも。
1 2 | int x , y ; int z = (x=10,y=20); |
最後の式の値を返すので、zの値は20になりますね。そのあたりを利用したマクロが量産される訳ですが。バッドテクニックと言えなくもないし広域に使うとまずそうだけど、局所的にたまに使います。データ加工したいときとか。
さて、アリスとロリータをカンマで繋ぎます。繋ぐ方法はいろいろあるので、いくつか試してみたのがこれ。どこでどうやってつながっているのかを理解するには、c++ の構文解析を「想像」する必要がありますよね。関数の引数で使うカンマと、オーバーライドできるカンマ演算子がまぜこぜになっているので、こんな感じになります。
“Alice”と”Lolita”をカンマでつなげるカンマ演算子の定義です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include "stdafx.h" #include <string> #include <iostream> using namespace std; std:: string operator , (std:: string &l, std:: string &r) { cout << "in operator , " << endl; std:: string s; s.append(l); s.append( "," ); s.append(r); return s; } std:: string comma(std:: string &l, std:: string &r) { cout << "in comma function 2 arguments " << endl; std:: string s; s.append(l); s.append( "," ); s.append(r); return s; } std:: string comma(std:: string &l) { cout << "in comma function 1 argument " << endl; return l; } int _tmain( int argc, _TCHAR* argv[]) { string s1 = "Alice" ; string s2 = "Lolita" ; std::cout << "ans: " << (s1, s2) << std::endl; std::cout << "ans: " << comma(s1, s2) << std::endl; std::cout << "ans: " << comma((s1, s2)) << std::endl; } |
■実行結果
1 2 3 4 5 6 7 | in operator , ans: Alice,Lolita in comma function 2 arguments ans: Alice,Lolita in operator , in comma function 1 argument ans: Alice,Lolita |
ちなみに、「カンマ演算子」なのか「コンマ演算子」なのかは諸説あるところで、わたくし的には「テクスト」と「テキスト」の違いを意識して(「コンテクスト」と「コンテキスト」とかも)、用語定義の哲学っぽく「カンマ演算子」という呼び名が好みです。そうそう、小数点の扱いも「ポイント」は「.」だったり「,」だったりする訳で、呼び名(発声)と現物(意味)とは違うよねという話。シニフィアンとシニフィエを久し振りに。