読者です 読者をやめる 読者になる 読者になる

Folioscope

プログラミング/Unix系/デザイン/CG などのメモがもりもり

順次演算子と区切り文字

C++では‘,‘(コンマ)にはいくつかの役割があります.
よく使われるものは,引数や変数宣言を区切るための記号です.
そしてC++では,コンマは順次演算子という演算子の意味もあります.

順次演算子とは

順次演算子は2項演算子の一つで,左側の式,右側の式の順に評価し,評価結果が右側の値となります.
例えば次の例,変数numに代入されるのは,順次演算子の右側の式を評価した結果の7です.
わざわざ括弧をつけているのは,演算子の優先順位が代入演算子より順次演算子の方が低いからです.

num = (1 + 2 , 3 + 4);  // num is 7

順次演算子はオーバーロードが可能な演算子なので,クラス内で次のように記述できます.

void operator, (int a) {  ...  }

実用的な使い方としては,ストリームの入出力クラスに見られる,シフト演算子(<<,>>)のような使い方が考えられます.
実際boostなどでは,順次演算子をオーバーロードした実装などが存在します.

引数の区切り文字と順次演算子

引数の区切り文字と,順次演算子が混在していた場合はどう処理されるのでしょうか.
下のソースの例では,引数の数が違う同じ名前の関数をオーバーロードしています.

int func(int a)
{ std::cout << "one arguments" << std::endl; }

int func(int a, int b)
{ std::cout << "two arguments" << std::endl; }
 
int main()
{
  func(1, 2);    // two arguments
  func((1, 2));  // one arguments

  return 0;
}

この例では,1番目の呼び出しでは,引数が2つと判断されています.
そこで括弧を使うことで,順次演算子として動作させることができました.

変数宣言の区切り文字と順次演算子

次の例は,コンパイルエラーとなります.

int a = 1, 2;  // compile error!!

これは変数宣言の区切り文字と認識されるため,1で初期化する変数aの宣言の後は,次の変数名が来るべきなのでコンパイルエラーとなります.
これも括弧をつけることで,意図した動作に.

int a = (1, 2);  // a is 2

コンマで区切っていたのが数値リテラルだったのでコンパイルエラーが出ただけで済みましたが,次の例はどうでしょうか.

int one() { return 1; }
int two() { return 2; }

int main()
{
  int a = one(), two();  // a is 1
}

この例ではコンパイルエラーは出ません.そしてaに代入される数値が,1となってしまいます.これはコンマが変数宣言の区切り文字と認識されてしまい,さらに変数twoというのが宣言されてしまうためです.


for文で複数の初期化式やカウンタ更新のための式を書くために,順次演算子を使っている人はたまに見ますが,可読性が落ちるために自分は使う実装に直面したことはこれまで無いです.
しかしC++の言語仕様としては存在しているので,知っていると役立つことがあるかもしれません.