ゆとりーなの日記

日記的な事を書いて行くと思はれる

関数型ってなんぞ

別にHaskellとかの話をしようってわけではありませんよと。C++の関数型ってのがイミフすぎるんですのよっていう話ですよと。
はい、まず関数型に似たようなもの?に関数ポインタってのがありますね。こんな風に使えますね。

#include <iostream>

void foo() {
  std::cout << "しーぷらー" << std::endl;
}

int main() {
  void (*ptr)() = foo; // &付けなくても勝手にアドレス取ってくれる
  ptr(); // 参照はがさなくてもなんか大丈夫
  (*ptr)();
  ptr = &foo; // &付けた方がお行儀が良い?
  ptr();
  (*ptr)(); // 参照はがした方がお行儀が良い?
  return 0;
}

構文が気持ち悪すぎですはい。因みにptrをconstにしたければこう書くみたいです。

#include <iostream>

void foo() {
  std::cout << "しーぷらー" << std::endl;
}

int main() {
  // void (const *ptr)() = foo; これは構文エラー
  void (* const ptr)() = foo;
  ptr();
  (*ptr)();
  ptr = &foo; // const である変数へは割り当てることはできません!
  ptr();
  (*ptr)();
  return 0;
}

typedefするとこう出来ますね。

#include <iostream>

void foo() {
  std::cout << "しーぷらー" << std::endl;
}

typedef void (*foo_ptr)();

int main() {
  const foo_ptr ptr = foo;
  ptr();
  (*ptr)();
  ptr = &foo; // const である変数へは割り当てることはできません!
  ptr();
  (*ptr)();
  return 0;
}

こっちの方が分かりやすいですね。
さて、関数型ですね。ポインタの時の流れでこんな風にやってみたくなったことありませんか?

#include <iostream>

void foo() {
  std::cout << "しーぷらー" << std::endl;
}

int main() {
  void (func)() = foo;
  func();
  return 0;
}

流石にありませんね、普通。失礼致しました。良く見たらこれ普通の関数宣言ですね。代入出来る要素がありません。
ところで次のようなコードは

#include <iostream>

void foo() {
  hoge();
}

void hoge() {
  std::cout << "しーぷらー" << std::endl;
}

int main() {
  foo();
  return 0;
}

hogeが無いって怒られますね。ここで次のように書いてみるとこれが通るんですね。

#include <iostream>

typedef void func(); // 関数型をtypdef

func hoge; // func型の変数宣言?

void foo() {
  hoge(); // 関数宣言?があるので怒られない
}

void hoge() {
  std::cout << "しーぷらー" << std::endl;
}

int main() {
  foo();
  return 0;
}

因みにhoge関数の定義を書かないとhogeが未定義って怒られますね。ということはやっぱりfunc hoge;は関数宣言ってことになるんですかね。
関数型怖すぎます。