Skip to content

Instantly share code, notes, and snippets.

@NeoCat
Created September 22, 2010 17:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NeoCat/592093 to your computer and use it in GitHub Desktop.
Save NeoCat/592093 to your computer and use it in GitHub Desktop.
#include <iostream>
using namespace std;
namespace vtstring {
// 文字列を表す可変引数テンプレート
template <char... a> struct vtstring;
template <char a, char... b>
struct vtstring<a, b...>
{
static const int size = 1 + vtstring<b...>::size; // サイズ
// C文字列を返す関数 (定数はダメ。初期化リスト未サポートのため?)
static const char* c_str() {
static const char ret[] = {a,b...,0}; return ret;
}
};
// NULL
template <>
struct vtstring<>
{
static const int size = 0;
static const char* c_str() { return ""; }
};
// 文字列の再帰的結合
template <class A, class... B>
struct join;
// 再帰
template <class A, class B, class... C>
struct join<A, B, C...>
{
typedef typename join<typename join<A,B>::result,
C...>::result result;
};
// 結合
template <char... a, char... b>
struct join<vtstring<a...>, vtstring<b...>>
{
typedef vtstring<a..., b...> result;
};
// 数値→文字列変換
template <int n>
struct from_int
{ // 10以上の場合
typedef typename from_int<n/10>::result tens;
typedef typename from_int<n%10>::result ones;
typedef typename join<tens, ones>::result result;
};
// 10未満の場合
#define DEF_FROM_INT(N) \
template <> struct from_int<N> { typedef vtstring<N+'0'> result; }
DEF_FROM_INT(0);
DEF_FROM_INT(1);
DEF_FROM_INT(2);
DEF_FROM_INT(3);
DEF_FROM_INT(4);
DEF_FROM_INT(5);
DEF_FROM_INT(6);
DEF_FROM_INT(7);
DEF_FROM_INT(8);
DEF_FROM_INT(9);
};
// FizzBuzz
template <int i>
struct fizzbuzz {
template <int n, int mod3, int mod5>
struct fizzbuzz_ {
typedef typename vtstring::from_int<n>::result result;
};
template <int n, int mod5>
struct fizzbuzz_<n, 0, mod5> {
typedef vtstring::vtstring<'F','i','z','z'> result;
};
template <int n, int mod3>
struct fizzbuzz_<n, mod3, 0> {
typedef vtstring::vtstring<'B','u','z','z'> result;
};
template <int n>
struct fizzbuzz_<n, 0, 0> {
typedef typename vtstring::vtstring<'F','i','z','z',
'B','u','z','z'> result;
};
typedef typename vtstring::join<
typename fizzbuzz_<i, i%3, i%5>::result,
vtstring::vtstring<'\n'>
>::result result;
};
// i〜maxをループしてTを適用(map)し, Mでfold
template <int i, int max, template<int n> class T,
template<class... A> class M>
struct loopN
{
typedef typename M<
typename T<i>::result,
typename loopN<i+1, max, T, M>::result
>::result result;
};
// 最後のループ
template <int max, template<int n> class T,
template<class... A> class M>
struct loopN<max, max, T, M>
{
typedef typename T<max>::result result;
};
int main()
{
// Hello World
typedef vtstring::vtstring<'H','e','l','l','o',','> str;
typedef vtstring::vtstring<'W','o','r','l','d','!'> str2;
typedef vtstring::join<str, str2>::result ret;
cout << ret::c_str() << endl;
// length of vtstring
cout << "length: " << ret::size << endl;
// Null string
typedef vtstring::vtstring<> null;
cout << null::c_str();
// int => vtstring
cout << vtstring::from_int<100>::result::c_str() << endl;
cout << "---" << endl;
// fizzbuzz
cout << loopN<1,100,fizzbuzz,vtstring::join>::result::c_str();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment