callback

はじめてコールバック関数のありがたみがわかった。いやまぁ、Windowsのイベントドリヴンなプログラムやってればイヤでも書くから今更何言ってんだって感じなんだけど(笑。

入出力、特にユーザに指示を仰ぐときとかは引数と戻り値が固定な(プレースホルダーって言うの?)コールバック関数のポインタを指定させてやると、コンソールでもウィンドウでも何でもござれになるのが嬉しいわけだ。そういやC標準のquicksort関数も確か関数ポインタ指定させてたよなー、とか思い出しながらファイルの上書き判断をコールバックでカホカホとコーディング。

enum query_value
{
  SKIP,
  OVERWRITE,
  OVERWRITE_ALL
};

typedef query_value (* query_func)(const char *);

query_value console_query(const char * filename)
{
  char query;
  std::cout << "The file " << filename << std::endl;
  std::cout << " is exists. Overwrite? [y]es, [n]o, [a]ll : ";
  do
  {
    std::cin >> std::setw(1) >> query;
    switch(tolower(query))
    {
      case 'y':
        return OVERWRITE;
      case 'n':
        return SKIP;
      case 'a':
        return OVERWRITE_ALL;
    }
  }while(true);
}

とか定義しておいて、

query_func query = console_query;

// 中略

if(query != NULL)
{
  switch(query(filename))
  {
    case SKIP:
      skip();
      break;

    case OVERWRITE:
      overwrite();
      break;

    case OVERWRITE_ALL:
      overwrite_all_flag = true;
      overwrite();
      break;
  }
}

ってな感じで使うわけだね。なんか記憶と勘だけで書いたのに一発で通ってしまった。console_queryの代わりにダイアログで指示を仰ぐdialog_queryも定義できるし、LinuxのXWindowとかで窓出すのもこうしとくと簡単に差し替えられるわけだ。quicksortは偉大だった。