忍者ブログ

どっかのゆとりのチラシの裏

plasma_effectのメモ帳的ブログのようなsomething

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

func_switch

なんか知らんけど夕方からずっとswitch構文のラッパー関数を作ってた。
複数の関数オブジェクトと引数のtupleとsize_t 変数を引数に渡しsize_t 変数の値によって関数オブジェクトを実行しその返り値を返すっていう関数である。
switch文で書くより見栄えが良くなるとか思いながら作ってたわけである。
とりあえずその実装コードと使用例どうぞ。
#include<type_traits>
#include<tuple>
#include<iostream>

//index_tuple
template<size_t... Num>struct index_tuple{};
template<size_t Max, size_t... Nums>struct index_count:index_count<Max - 1, Max, Nums...>{};
template<size_t... Nums>struct index_count<0, Nums...>
{
using type = index_tuple<0, Nums...>;
};

//type_num
template<class Type, class... Types>struct type_num
{
static const int value = 1 + type_num<Types...>::value;
};
template<class Type>struct type_num<Type>
{
static const int value = 1;
};

//tuple_num
template<class Ty>struct tuple_num;
template<class... Types>struct tuple_num<std::tuple<Types...>>
{
static const int value = type_num<Types...>::value;
};

//func_tuple
template<class RetType, class ArgTupleTy, class FuncTy, class ArgTy>struct func_tuple_impl;
template<class RetType, class ArgTupleTy, class FuncTy, size_t... Nums>
struct func_tuple_impl<RetType, ArgTupleTy, FuncTy, index_tuple<Nums...>>
{
static RetType run(ArgTupleTy tup, FuncTy func)
{
return func(std::get<Nums>(tup)...);
}
};
template<class RetType, class ArgTupleTy, class FuncTy>
using func_tuple = func_tuple_impl<RetType, ArgTupleTy, FuncTy,
typename index_count<tuple_num<ArgTupleTy>::value - 1>::type>;

//func_switch
template<class RetType, class ArgTupleTy, class FuncTy, class... FuncTypes>
struct func_switch_impl
{
static RetType run(size_t switch_on, ArgTupleTy tup, FuncTy func, FuncTypes... funcs)
{
return (switch_on == 0 ?
func_tuple<RetType, ArgTupleTy, FuncTy>::run(tup, func)
: func_switch_impl<RetType, ArgTupleTy, FuncTypes...>
::run(switch_on - 1, tup, funcs...));
}
};
template<class RetType, class ArgTupleTy, class FuncTy>
struct func_switch_impl<RetType, ArgTupleTy, FuncTy>
{
static RetType run(size_t, ArgTupleTy tup, FuncTy func)
{
return func_tuple<RetType, ArgTupleTy, FuncTy>::run(tup, func);
}
};
template<class RetType, class ArgTupleTy, class... FuncTypes>
inline RetType func_switch(size_t switch_on, ArgTupleTy tup, FuncTypes... funcs)
{
return func_switch_impl<RetType, ArgTupleTy, FuncTypes...>::run(switch_on, tup, funcs...);
}

//example
auto x = [](int, int, int)->int{return 0; };
auto y = [](int a, int b, int c)->int{return a + b + c; };
auto z = [](int, int, int)->int{return 1; };

int main()
{
auto w = func_switch<int>(1, std::tuple<int, int, int>(1, 2, 3), x, y, z);
std::cout << w << std::endl;
std::cin.get();
}




なげーよクソボケって話なのだが。
とりあえずこれでswitch構文のラッパーみたいなのが出来た。

どこから話せばいいねんっていう話ではあるが。上から解説していこう。
なおどっからどう見てもstructって書いてあるのも区別するのは面倒なのでクラスとしている。

まずindex_tupleトリックを実行するためのindex_tupleとindex_countを定義している。
index_tupleトリックを知らない人のために一応簡単にindex_tupleトリックを説明する。
可変長テンプレート整数引数を渡す時0からN-1のように連続した値を渡したい時がある。
最初に可変長テンプレート整数引数をとるクラスindex_tupleを定義する。実装はなんでもいい。
で、もう一つ(こっちがメインとなる)クラスを定義する。ここではカウントダウン的に使うのでindex_countとした。
そのメンバでindex_tupleをusingエイリアスする。すなわちusing type = index_tuple<0,1,...,N-1>とするわけである。
そしてこのindex_tupleトリックを使うにあたりテンプレートクラス引数を1つとるクラスを定義する。
そして可変長テンプレート整数引数Numsを取ってindex_tuple<Nums...>で特殊化する。特殊化したクラスの内部で(例えばstatic関数で)対象のテンプレート引数にNums...を渡すわけだ。
そしてindex_count<N>::typeをこのクラスに渡すのである。
この型はindex_tuple<0,1,...,N>のusingエイリアスのはずなので特殊化された方で使われる。
したがって順に並んだ数字をテンプレート引数に渡せるというわけである。

次にtype_numの実装である。要は可変長テンプレート引数の引数の数を数えるクラスである。
これは説明不要だろう。

その次はtuple_numの実装。tupleを渡しそのテンプレート引数の数を数えるクラス。これはtype_numとクラスの特殊化で実装可能。

その次がfunc_tupleの実装である。tupleに固められた引数と関数を渡してその引数を関数に渡し実行させる。ここでさっきのindex_tupleトリックが役立つのである。
すなわちtuple引数をtup、関数引数をfuncとしてfunc(std::get<hoge>...)とするのである。
綺麗に使うためにusingと補助クラスを定義した。ここでtypenameを使っているのはtuple_num::valueが定義されない可能性があるからだ。多分。とりあえずコンパイラに怒られたのでtypenameをつけたが、多分原因はそれだと思われる。

最後にfunc_switchの実装である。再帰を利用してswitch_onが0になるかfuncが1個になるかで関数を実行させる。

使い道は多分ある。多分。
PR

コメント

お名前
タイトル
文字色
メールアドレス
URL
コメント
パスワード Vodafone絵文字 i-mode絵文字 Ezweb絵文字

カレンダー

07 2017/08 09
S M T W T F S
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31

フリーエリア

最新CM

[02/12 kariya_mitsuru]
[10/14 どっかの京大生o]
[10/04 どっかのZ会生y]
[07/31 どっかのZ会生y]
[07/31 GNR]

プロフィール

HN:
plasma_effect
性別:
非公開

バーコード

ブログ内検索

最古記事

(06/08)
(06/18)
(06/21)

P R