C++11

C++11のラムダ式で遊んでみた

More than 1 year has passed since last update.

恥ずかしながらC++ほとんど書いたことないけど、C++11だとラムダ式が入ったので静的型付け関数型言語のようなことをできるんじゃないか、と思って適当に書いてみた。

こんなかんじでC++11の機能が使えるらしい

clang++ -std=c++11 -stdlib=libc++ hello.cpp -o hello

clang v3.2。本当にC++について何も知らなかったので、このオプションに気づくまで一時間かかった

参考: 本の虫: lambda 完全解説 http://cpplover.blogspot.jp/2009/11/lambda.html

とりあえずmap, each, selectを定義して遊んでみる。

#include <iostream>
#include <memory>
#include <cmath>
#include <vector>

namespace prelude {
    template<class T, class F>
    auto map(const std::vector<T> & vec, F fun) -> std::vector<decltype(fun(vec[0]))> {
        std::vector<decltype(fun(vec[0]))> ret;
        std::transform (vec.begin(), vec.end(), std::back_inserter(ret), fun);
        return ret;
    }

    template<class T, class F>
    std::vector<T> select(const std::vector<T> & vec, F fun) {
        std::vector<T> ret;
        std::for_each (vec.begin(), vec.end(), [&](const T &t){
            if(fun(t)) ret.push_back(t);
        });
        return ret;
    }

    template<class T, class F>
    void each(const std::vector<T> & vec, F fun) {
        for_each (vec.begin(), vec.end(), fun);
    }
}

struct Point {
  Point(int x, int y): x(x), y(y) {};
  int x;
  int y;
};
typedef std::shared_ptr<Point> PointPtr;

double getDistance(const Point& p1, const Point& p2) {
  return std::sqrt(std::pow(p1.x - p2.x, 2)+std::pow(p1.y - p2.y, 2));
}

using namespace prelude;
using namespace std;

int main() {
    //lambda
    [](){cout << "Hello,World" << endl;}();

    function<int(int, int)> multiply = [](int x, int y) -> int { return x * y;};
    cout << multiply(1,4) << endl;

    const int z = 5;
    auto multiply5 = [z](int x){return x * z;};
    cout << multiply5(4) << endl;

    Point p1(1,5);
    Point p2(3,2);
    Point p3(4,3);

    cout << getDistance(p1, p2) << endl;;

    vector<Point> vec;
    vec.push_back(p1);
    vec.push_back(p2);
    vec.push_back(p3);

    {
        auto vec2 = map(vec, [](const Point &p){
            return p.x * 2;
        });

        each(vec2, [](int i) {
            cout << i << endl;
        });
    }

    each(vec, [](const Point &p){cout << p.x << endl;});
    auto vec3 = select(vec, [](const Point &p) -> bool { return p.x > 2 ;});
    each(vec3, [](const Point &p){cout << p.x << endl;});
}

途中 @krustf @mickey24 @mashiro に constにしろback_insert使えとかdecltype使えば動的に型つくれるよ、みたいな感じで教えてもらったりした。
メモリと参照意識するの結構難しいけどどこで実体作ってどこで参照コピーしてるかなんとなく想像できるようになってきた。

auto と std::function 便利ィ…
using namespace std; するな死にたいのか!と言われたけど main だけに絞ったので許してほしい感じです