忍者ブログ

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

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

[PR]

×

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

index_rangeの再帰深度対数オーダー実装

現在スライド作りのためにコンパイル時処理簡易ライブラリを作っているところである。そのライブラリには当然再帰深度が対数オーダーのindex_rangeも含まれる。それを公開しようと思った。部分的公開に近い。この詳しい話については中3女子氏のブログにある(http://d.hatena.ne.jp/boleros/20120406/1333682532)。
#pragma once
#include"type_traits.hpp"
#include"preprocess.hpp"

namespace dcl
{
//index_tuple
template<int...>struct index_tuple{};

namespace detail
{
//get_index_next
constexpr int get_index_next(int a)
{
return (a%2==0 ? a/2 : (a-1)/2);
}


//index_next
template<class Index,int N,bool is_even>struct index_next;
template<int N,int... Nums>//even
struct index_next<dcl::index_tuple<Nums...>,N,true>
{
using type = index_tuple<Nums...,(N+Nums)...>;
};
template<int N,int... Nums>//odd
struct index_next<dcl::index_tuple<Nums...>,N,false>
{
using type = index_tuple<Nums...,(N+Nums)...,2*N>;
};
template<>//0
struct index_next<dcl::index_tuple<>,0,false>
{
using type = index_tuple<0>;
};


//index_count_impl
template<int End>struct index_count_impl
{
using type = typename index_next<
typename index_count_impl<get_index_next(End)>::type,
get_index_next(End),
End%2==0>::type;
};

template<>struct index_count_impl<0>
{
using type = index_tuple<>;
};
}
//index_count
template<size_t N>class index_count
{
public:
using type = typename detail::index_count_impl<N>::type;
};

//index_range
namespace detail
{
template<class,int,int>struct index_range_impl;
template<int... Nums,int Start,int Step>
struct index_range_impl<index_tuple<Nums...>,Start,Step>
{
using type = index_tuple<(Start+Nums*Step)...>;
};
}
template<int Start,int End,int Step=1>class index_range
{
public:
using type = typename detail::index_range_impl<
typename index_count<1+(End-Start)/Step>::type,
Start,
Step>::type;
};

//index_merge
namespace detail
{
template<class,class,class,class,class,class>struct index_merge_impl;
template<int... NumsA,int... NumsB,int... NumsC,int... NumsD,int... NumsE,int... NumsF>
struct index_merge_impl<
index_tuple<NumsA...>,
index_tuple<NumsB...>,
index_tuple<NumsC...>,
index_tuple<NumsD...>,
index_tuple<NumsE...>,
index_tuple<NumsF...>>
{
using type = index_tuple<NumsA...,NumsB...,NumsC...,NumsD...,NumsE...,NumsF...>;
};
}
template<class IndexA,class IndexB,class IndexC=index_tuple<>,class IndexD=index_tuple<>,class IndexE=index_tuple<>,class IndexF=index_tuple<>>class index_merge
{
public:
using type = typename detail::index_merge_impl<IndexA,IndexB,IndexC,IndexD,IndexE,IndexF>::type;
};

//DCL_COUNT_DOWN_USING
#define DCL_COUNT_DOWN_USING(TO,FROM)\
template<class>struct DCL_PP_CAT(impl_index_range_cat_,TO);\
template<int... Nums>struct \
DCL_PP_CAT(impl_index_range_cat_,TO)<dcl::index_tuple<Nums...>>\
{using type = FROM<Nums...>;};\
template<int N>\
using TO = typename DCL_PP_CAT(impl_index_range_cat_,TO)\
<typename dcl::index_count<N>::type>::type;

//DCL_INDEX_RANGE_USING
#define DCL_INDEX_RANGE_USING(TO,FROM)\
template<class>struct DCL_PP_CAT(impl_index_range_cat_,TO);\
template<int... Nums>struct \
DCL_PP_CAT(impl_index_range_cat_,TO)<dcl::index_tuple<Nums...>>\
{using type = FROM<Nums...>;};\
template<int Start,int End,int Step=0>\
using TO = typename DCL_PP_CAT(impl_index_range_cat_,TO)\
<typename dcl::index_range<Start,End,Step>::type>::type;

}







DCL_PP_CATはトークン名結合のプリプロセッサマクロである。
ちなみにこれ、中3女子氏のコードを途中まで読んで途中から自分の思いのまま実装したためどこらへんが違うかさっぱりわからない。誰か差分作ってくれないかなぁって感じ。
PR

func_switchのヘッダ

この前のfunc_switch、ヘッダにまとめて使ってたりする。
そのソースコード貼っとくのでテキトーに使って、どうぞ。
使いかた:テキトーにヘッダファイル用意してコピペしてそのヘッダをインクルード
VC++での使用を基本としてるのでpragma onceが使えない環境ではマクロを使った一般的なインクルードガードに差し替えてください。

なんかfunc_switchに関係ない関数見えるけど気にしない


#pragma once
#include<type_traits>
#include<tuple>
#include<stdexcept>

namespace dyz_type_traits
{
using void_tuple = std::tuple<void*>;
void_tuple enabler;

template<class Type, class Type2, class... Types>struct all_type_equal_impl
{
static const bool value = std::is_same<Type, Type2>::value
&& all_type_equal_impl<Type, Types...>::value;
};
template<class Type, class Type2>struct all_type_equal_impl<Type, Type2>
{
static const bool value = std::is_same<Type, Type2>::value;
};
template<class Type, class... Types>class are_same
{
public:
static const bool value = all_type_equal_impl<Type, Types...>::value;
};

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...>;
};

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;
};

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

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>;

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...);
}
template<class RetTy,class... Types>inline typename std::enable_if<are_same<RetTy,Types...>::value,RetTy>::type
number_filter(size_t num, Types... nums)
{
return func_switch<RetTy>(num, std::tuple<int>(), [=](int){return nums; }...);
}
template<class Ty>inline void iterator_shift(Ty& ite, int shift)throw(std::out_of_range)
{
if (shift > 0)
{
for (int i = 0; i < shift; ++i)
{
++ite;
}
}
else
{
for (int i = 0; i > shift; --i)
{
--ite;
}
}
}

}

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構文のラッパーみたいなのが出来た。

カレンダー

03 2024/04 05
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

フリーエリア

最新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