エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

自作の演算子

最近になってBoost::fc++というのを知りました。C++関数型言語風に使おうというライブラリなのですが、その中に次のような記述があるのを見つけました。

x %plus% y

おぉ、演算子を自作している!
この発想はなかったので、ちょっと衝撃でした。
この式を普通の関数呼び出しの形式に展開すると、

operator % (x, plus).operator % (y)

となるわけで、%演算子オーバーロードがキモになっているようです。

そんな訳で、これをまねて、自作の演算子を実装してみました。

// 演算子の基底クラス
struct Op
{
    virtual ~Op() {}
    virtual int eval(int lhs, int rhs) const = 0;
};

// 演算する値と演算子を演算まで中継するクラス
class Result
{
public:
    Result(int lhs, const Op& op) : lhs_(lhs), op_(op) {}
    int operator % (int rhs) { return op_.eval(lhs_, rhs); }

private:
    int       lhs_;
    const Op& op_;
};

// 最初の%(左側の値と演算子をバインドする)
Result operator % (int lhs, const Op& op)
{
    return Result(lhs, op);
}

// ここから使用例

struct Plus : public Op
{
    int eval(int lhs, int rhs) const { return lhs + rhs; }
};

struct Minus : public Op
{
    int eval(int lhs, int rhs) const { return lhs - rhs; }
};

struct Times : public Op
{
    int eval(int lhs, int rhs) const { return lhs * rhs; }
};

const Plus  plus;
const Minus minus;
const Times times;

#include <iostream>

int main(int, char* [])
{
    int  x = 12;
    int  y = 34;

    std::cout << (x %plus% y)  << std::endl;
    std::cout << (x %minus% y) << std::endl;
    std::cout << (x %times% y) << std::endl;

    return 0;
}

Result::operator %の中で演算結果を返してますが、代わりに関数オブジェクトなどを返すことで遅延演算もできるはずです。