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

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

畳み込み、ただしC++テンプレートで

// リンクの終端
struct Nil {};

// 左畳み込みテンプレート
template<template<typename, typename> class Operator, typename N, typename Sequence>
struct Foldl
{
    static const int value = Foldl<
                                 Operator,
                                 Operator<N, typename Sequence::head>,
                                 typename Sequence::tail
                             >::value;
};

// 左畳み込みテンプレート(終端処理)
template<template<typename, typename> class Operator, typename N>
struct Foldl<Operator, N, Nil>
{
    static const int value = N::value;
};

// 以下、畳み込みの利用例

// 整数-型変換テンプレート
template<int N>
struct Int
{
    static const int value = N;
};

// N から 1 までのシーケンスを生成するテンプレート
template<int N>
struct DownToOne
{
    typedef Int<N>           head;
    typedef DownToOne<N - 1> tail;
};

// N から 1 までのシーケンスを生成するテンプレート(終端)
template<>
struct DownToOne<1>
{
    typedef Int<1> head;
    typedef Nil    tail;
};

// 加算演算子テンプレート
template<typename T, typename U>
struct Add
{
    static const int value = T::value + U::value;
};

// 10 から 1 までを初期値 0 から加算で左畳み込み( ((((((((((0 + 10) + 9) + 8) + 7) + 6) + 5) + 4) + 3) + 2) + 1) )
int n = Foldl<Add, Int<0>, DownToOne<10>>::value;


実行結果。

$ g++ --std=c++11 -S foldl.cpp 
$ cat foldl.s 
	.section	__TEXT,__text,regular,pure_instructions
	.section	__DATA,__data
	.globl	_n                      ## @n
	.align	2
_n:
	.long	55                      ## 0x37

つづく。