Created
July 3, 2011 16:05
-
-
Save maraigue/1062342 to your computer and use it in GitHub Desktop.
「一言書くだけで末尾再帰最適化」をC++でやってみた
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 元ネタ:http://d.hatena.ne.jp/wasabiz/20110118/1295335821 | |
// | |
// 注意点: | |
// ここで定義されているTCO_FUNCは、「末尾再帰で書かれた関数の引数が2つである場合」 | |
// に限定された定義です。 | |
// それ以上の場合は、別途マクロを定義しないとならないです。 | |
// Boost.PPとかを使うと何とかなるのかな…? | |
#ifndef _OPT_TAIL_RECURSION_H_ | |
#define _OPT_TAIL_RECURSION_H_ | |
#define TCO_FUNC(FUNCTYPE, FUNCNAME, ARGTYPE1, ARGNAME1, ARGTYPE2, ARGNAME2) \ | |
class FUNCNAME##_calculator__{ \ | |
private: \ | |
FUNCTYPE __result__; \ | |
bool __tail_recursed__; \ | |
ARGTYPE1 __##ARGNAME1##__; \ | |
ARGTYPE2 __##ARGNAME2##__; \ | |
\ | |
public: \ | |
FUNCNAME##_calculator__(ARGTYPE1 ARGNAME1, ARGTYPE2 ARGNAME2){ \ | |
for(;;){ \ | |
__tail_recursed__ = false; \ | |
__result__ = (*this)(ARGNAME1, ARGNAME2); \ | |
\ | |
if(__tail_recursed__){ \ | |
ARGNAME1 = __##ARGNAME1##__; ARGNAME2 = __##ARGNAME2##__; \ | |
}else{ \ | |
break; \ | |
} \ | |
} \ | |
} \ | |
\ | |
FUNCTYPE FUNCNAME(ARGTYPE1 ARGNAME1, ARGTYPE2 ARGNAME2){ \ | |
__##ARGNAME1##__ = ARGNAME1; \ | |
__##ARGNAME2##__ = ARGNAME2; \ | |
__tail_recursed__ = true; \ | |
} \ | |
\ | |
FUNCTYPE operator ()(ARGTYPE1 ARGNAME1, ARGTYPE2 ARGNAME2); \ | |
FUNCTYPE operator [](int dummy){ return __result__; } \ | |
}; \ | |
\ | |
FUNCTYPE FUNCNAME(ARGTYPE1 ARGNAME1, ARGTYPE2 ARGNAME2){ \ | |
FUNCNAME##_calculator__ calculator(ARGNAME1, ARGNAME2); \ | |
return calculator[0]; \ | |
} \ | |
\ | |
FUNCTYPE FUNCNAME##_calculator__::operator ()(ARGTYPE1 ARGNAME1, ARGTYPE2 ARGNAME2) | |
#endif // _OPT_TAIL_RECURSION_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "opt-tail-recursion.h" | |
TCO_FUNC(long long, sum1, long long, count, long long, acc){ | |
if(count == 0) return acc; | |
return sum1(count - 1, acc + count); | |
} | |
long long sum2(long long count, long long acc){ | |
if(count == 0) return acc; | |
return sum2(count - 1, acc + count); | |
} | |
/* | |
long long sum(long long count, long long acc = 0){ | |
if(count == 0) return acc; | |
return sum(count - 1, acc + count); | |
} | |
*/ | |
int main(void){ | |
std::cout << sum1(1000000, 0) << std::endl; | |
std::cout << sum2(1000000, 0) << std::endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment