More Related Content
PDF
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ PDF
実践・最強最速のアルゴリズム勉強会 第一回 講義資料(ワークスアプリケーションズ & AtCoder) PDF
PDF
PDF
PPTX
katagaitai CTF勉強会 #3 crypto PPTX
PDF
What's hot
PDF
PDF
PDF
PDF
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話 PDF
PDF
PDF
PDF
ODP
Goのサーバサイド実装におけるレイヤ設計とレイヤ内実装について考える PDF
PDF
PDF
PDF
ネットワーク ゲームにおけるTCPとUDPの使い分け PDF
Vue.jsでFormをAtomic Designしてみた時のコンポーネント間のデータのやりとり PDF
PDF
PDF
PDF
PDF
PDF
Similar to リテラル文字列型までの道
PDF
PDF
中3女子が狂える本当に気持ちのいい constexpr PDF
PDF
PDF
C++のSTLのコンテナ型を概観する @ Ohotech 特盛 #10(2014.8.30) PDF
KEY
Algebraic DP: 動的計画法を書きやすく PDF
PDF
プログラミング講座 #6 競プロのテクニック(初級) PDF
PDF
PDF
アルゴリズムのお勉強 アルゴリズムとデータ構造 [素数・文字列探索・簡単なソート] PDF
C++0x in programming competition PDF
PDF
PDF
PDF
2011.12.10 関数型都市忘年会 発表資料「最近書いた、関数型言語と関連する?C++プログラムの紹介」 PDF
PDF
C++ Template Meta Programming の紹介@社内勉強会 PDF
リテラル文字列型までの道
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 8.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 9.
- 10.
constexprの確認
• コンパイル時定数作ったり定数式作ったりするキーワード
• 定数式の実装は実質return文一つ
•classが条件を満たせばリテラル型と扱われconstexprで使える
• 別の非volatileなリテラル型のみをメンバ変数に持ち、「aggregateである」か
「1つ以上のムーブでもコピーでもないconstexprコンストラクタと
トリビアルなデストラクタ(要はユーザー定義されてない)を持つ」
• intなどの基本データ型はリテラル型、要はこれらから再帰的に定義される
• aggregateの条件は後に載せる
• templateなconstexpr宣言された関数について、constexpr関数の
制約に合わないインスタンス化された場合ill-formedにはならないが
普通の関数として扱われる
• constexprメンバ関数は暗黙でconst修飾される(後に問題になる)
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
展開の仕方にも色々ある
• 例えばtemplate<size_t… Nums>があるとして0,1,2,3を渡したとする
•size_t x[]={ Nums… }でsize_t x[]={ 0 , 1 , 2 , 3 } に展開される
• size_t y[]={ x[Nums]… }でsize_t y[]={ x[0] , x[1] , x[2] , x[3] }に
• size_t z[]={ (4 + Nums)… }でsize_t z[]={ 4 , 5 , 6 , 7 }に展開される
• size_t w[]={ func( Nums )… }で
size_t w[]={ func(0), func(1), func(2), func(3) }
- 20.
- 21.
- 22.
その他雑多なこと
using エイリアス
• usinghoge = piyo;でhogeがpiyoと同じになる
• templateも可能(template<int N>using hoge = piyo<N>;など)
static_assert
• コンパイル時整数定数と文字列リテラルを渡して使う
• 整数定数がfalseなら文字列を出力してコンパイルエラーになる
typename
• templateをほげほげするコードだと型であるか分からない時がある
• これをつけておくと「型である」とコンパイラに伝えられる
- 23.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 24.
- 25.
- 26.
- 27.
- 28.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 29.
- 30.
- 31.
- 32.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 33.
- 34.
- 35.
- 36.
- 37.
enable_if
• どうやって使うの
• 例えばこんな使い方がある
template<size_tN>typename enable_if<(N%2==0),bool>::type
hoge(){return true;}
template<size_t N>typename enable_if<!(N%2==0),bool>::type
hoge(){return false;}
• enable_ifを使うのにtypenameがいるのは第1引数の値によってそも
そもtypeが存在しない場合があるため
• Nが奇数なら上はtypeが存在しないので置き換え失敗
• Nが偶数なら下はtypeが存在しないので置き換え失敗
• これで条件によって実装分岐が出来た
- 38.
- 39.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 40.
- 41.
index_tuple
• とりあえずtemplate<int… Nums>structindex_tuple;を定義する
• テンプレート引数でclassを取るようにテンプレートクラスを定義、
index_tuple<Nums…>で特殊化しその時渡したいクラスの
テンプレート引数にNums…を渡してホゲホゲする
• 何らかのクラスがメンバにusing type = index_tuple<Nums…>を持つ
ようにして先ほどのクラスにtypeを渡せば目的が達成される
- 42.
- 43.
- 44.
準備
• 前の結果のindex_tupleを次の最大値をもらってそこから次の
index_tupleを返すメタ関数を作る
template<class Index,intN,bool is_odd>struct index_count_next;
template<int… Nums,int End>
struct index_count_next<index_tuple<Nums…>,End,true>
{using type = index_tuple<Nums…,(End+Nums)…>;};
Template<int… Nums,int End>
struct index_count_next<index_tuple<Nums…>,End,false>
{using type = index_tuple<Nums…,(End+Nums)…,2*End>;};
template<>struct index_count_next<index_tuple<>,0,false>
{using type = index_tuple<0>;};
• 0に繋がるのは1のみであるためこのように特殊化して問題はない
- 45.
- 46.
要はこう
constexpr int get_next(intN){return (N%2 == 0 ? N/2 : (N-1)/2);}
template<int N>struct index_count{
using type = index_count_next<
index_count< get_next(N) >::type ,
get_next(N) ,
N%2==0)>::type;
};
template<>struct index_count<0>{
using type = index_tuple<>;
};
- 47.
- 48.
じゃあどうするの
• こんな感じでいいっしょ
template<class,int,int>struct index_range_impl;
template<int…Nums,int Step,int Start>struct
index_range_impl<index_tuple<Nums…>,Step,Start>
{using type = index_tuple<(Start*Nums+Step)…>;};
template<int Start,int End,int Step>
using index_range = index_range_impl<typename
index_count< 1 + (End-Start)/Step >::type , Step , Start>;
• enable_if使ってEnd-Start/Step<0の時index_tuple<>を
typeにするのもアリ
- 49.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
実装
template<class,class,size_t>struct array_lap_impl;
template<int… Nums,classTy,size_t SIZE>
struct array_lap_impl<index_tuple<Nums…>,Ty,SIZE>{
static constexpr array<Ty,SIZE> get(const Ty (&ar)[SIZE])
{ return array<Ty,SIZE>{ar[Nums]…}; } };
template<class Ty,size_t SIZE>
constexpr array<Ty,SIZE> array_lap(const Ty (&ar)[SIZE])
{return array_lap_impl<typename
index_count<SIZE>::type,Ty,SIZE>::get(ar); }
- 59.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 60.
- 61.
- 62.
- 63.
index_rangeを使おう
template<class>struct array_replace;
template<int… Nums>structarray_replace {
template<class Ty,size_t ArgSIZE,size_t RetSIZE>
static constexpr array<Ty,RetSIZE>
get(const array<Ty,ArgSIZE>& ar)
{return array<Ty,ReSIZE>{ar[Nums]…};}};
template<size_t Start,size_t End,class Ty,size_t SIZE>
constexpr array<Ty,End-Start+1>array_cut(const array<Ty,SIZE>& ar)
{return array_replace<typename
index_range<Start,End>::type>::get<Ty,ArgSIZE,RetSIZE>(ar);}
• Start番目からEnd番目の要素を抜き出す関数
- 64.
- 65.
2つのarrayと2つのindex_count
template<class,class>struct array_merge_impl;
template<int… NumsA,int…NumsB>struct array_merge_impl
<index_tuple<NumsA…>,index_tuple<NumsB…>>{
template<class TyA,size_t SIZEA,class TyB,size_t SIZEB>
static constexpr array<TyA,SIZEA+SIZEB>
get(const array<TyA,SIZEA>& arA,const array<TyB,SIZEB>& arB)
{return array<TyA,SIZEA+SIZEB>
{arA[NumsA]…,static_cast<TyA>(arB[NumsB])…};}};
template<class TyA,size_t SIZEA,class TyB,size_t SIZEB>
constexpr array<TyA,SIZEA+SIZEB>
array_merge(const array<TyA,SIZEA>& arA,const array<TyB,SIZEB>& arB)
{return array_merge_impl
<typename index_count<SIZEA>::type, typename index_count<SIZEB>::type>
::get(arA,arB);}
• 一つのスライドに収めるもんじゃねぇ
- 66.
- 67.
for_eachの実装
template<class>struct for_each_impl;
template<size_t Nums…>classfor_each_impl<index_tuple<Nums…>>{
template<class RetTy,class ArgTy,size_t SIZE,class FuncTy>
constexpr array<RetTy,SIZE>
get(const array<ArgTy,SIZE>& ar,FuncTy& func)
{return array<RetTy,SIZE>{ func(ar[Nums])… };} };
template<class RetTy,class ArgTy,size_t SIZE,class FuncTy>
constexpr array<RetTy,SIZE>
for_each(const array<RetTy,SIZE> &ar,FuncTy& func)
{return for_each_impl<typename index_count<SIZE>::type>
::get<RetTy>(ar,func);}
• 実行時に要素を直接いじるfor_eachも考えたかったけど面倒だった
• decltype使えばいいことに気づいたのは上のコード書いた後だった
- 68.
- 69.
こんな感じ
template<class Ty,size_t Num,classFuncTy>
constexpr size_t match_num
(array<Ty,Num>& ar,FuncTy& func,size_t start=0,size_t end=Num-1)
{return (start==end ? static_cast<bool>(func(ar[start])) :
match_num(ar,func,start,(start+end)/2) +
match_num(ar,func,(start+end)/2+1,end));}
• startからendまでチェック
• 分割地点については→
- 70.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 71.
- 72.
- 73.
- 74.
文字列を結合する
• 2つの文字列を結合させたい
• 文字列aとbをa+bで結合させる
•aの末端はnull文字なのでそれは無視する
• するとこう
template<class T,size_t SA,size_t SB>basic_string<T,SA+SB-1>
operator+(const basic_string<T,SA>& a,const basic_string<T,SB>& b)
{return basic_string<T,SA+SB-1>(array_merge(array_cut<0,SA-2>(a.str_),b.str_));}
- 75.
- 76.
- 77.
実装
template<class Ty>constexpr Tyget_digit_num(int num,int digit)
{return static_cast<Ty>(static_cast<int>(’0’) +
( (num /pow(10,digit) )%10));
template<class,class,size_t>struct to_string_impl;
template<int… Nums,class Ty,size_t SIZE>
struct to_string_impl<index_tuple<Nums…>,Ty,SIZE>{
static constexpr array<Ty,SIZE> get(const int& num)
{return array<Ty,SIZE>{get_digit_num(num,SIZE-Nums-1)…};}};
• pow(int,int)はmath.hppあたりにでも定義しときましょう
• ‘0’の文字コードを知らなくてもできる実装(速度とか知らん)
- 78.
- 79.
実装
template<class Ty,size_t SIZE>constexprbool string_equal_impl
(const array<Ty,SIZE>& a,const array<Ty,SIZE>& b,
size_t start=0,size_t end=SIZE-1){
return ( start==end ? a[start]==b[start] :
string_equal_impl(a,b,start,(start+end)/2))&&
string_equal_impl(a,b,(start+end)/2+1),end);}
template<class TyA,size_t SA,class TyB,size_t SB>constexpr typename
enable_if<(SA==SB)&&(is_same<TyA,TyB>::value),bool>::type
operator==(const basic_string<TyA,SA>& a,
const basic_string<TyB,SB>&b){return string_equal_impl(a,b);}
template<class TyA,size_t SA,class TyB,size_t SB> constexpr typename
enable_if<!((SA==SB)&&(is_same<TyA,TyB>::value)),bool>::type
operator==(const basic_string<TyA,SA>& a,
const basic_string<TyB,SB>&b){return false;}
• 長い、長すぎる
• なおis_sameの出番ここで終了の模様
- 80.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
途中結果を引数として渡す工夫
• Is_numとget_numはそれぞれ数字のチェックと数字のゲット
constexpr intstring_to_integer(string str,int ret,size_t start,size_t end)
{return start==end ?
(is_num(str.str_[start]) ? 10*ret + get_num(str.str_[start]) : ret)
: string_to_integer(
str , string_to_integer
(str , ret , start , (start+end)/2 ),
(start+end)/2+1,end) );}
- 93.
他にも作ろうとしたもの
• 文字列逆転
• abcdをdcbaにするみたいな
•index_rangeとarray_replaceとarray_mergeを使ってほげほげ
• 文字列切り取り
• DtYaZsKからYaZsを取り出したいとか
• ポインタとindex_countで揃える
• 文字列一部抹消
• 上の逆でDtYaZsKからDtKを取り出すみたいな
• index_countとindex_rangeを組み合わせて云々
• 置換関数にnull文字だけの配列渡したほうが早い気もする
- 94.
やること一覧
• 前回の復習+必要なC++の仕様の確認
• C++的メタプログラミングとは
•ライブラリの仕様を考えよう
• 汎用的メタ関数を作ろう(type_traits.hpp)
• 強化型index_tupleとは(index_tuple.hpp)
• 配列のラッパーを作る(array.hpp)
• 配列の操作をしよう(array_algorithm.hpp)
• 文字列型を作ろう(basic_string.hpp)
• そしてコンパイル時文字列操作へ…(string_control.hpp)
• 参考資料とまとめ
- 95.
- 96.
- 97.
参考資料(スライド編)
• ボレロ村上氏のスライド
• 中3女子でもわかるconstexpr
http://www.slideshare.net/GenyaMurakami/constexpr-10458089
• 中3女子が狂える本当に気持ちのいい constexpr
http://www.slideshare.net/GenyaMurakami/constexpr-11509325
• constexpr中3女子テクニック
http://www.slideshare.net/GenyaMurakami/constexpr-23355469
• すごいconstexprたのしくレイトレ!
http://www.slideshare.net/GenyaMurakami/constexpr-29223898
• 蔵人紗音のじ氏のスライド
• Template Meta Programming入門から応用まで
https://dl.dropboxusercontent.com/u/43530447/tmp_web.pdf
- 98.
参考資料(サイトや文献編)
• ENiyGmaA Codehttp://d.hatena.ne.jp/boleros/
• index_tuple イディオムにおける index_range の効率的な実装
http://d.hatena.ne.jp/boleros/20120406/1333682532
• Wonderlands in Usagi's brain http://blog.wonderrabbitproject.net/
• C++におけるtemplateキーワードの効果の忘却とついでにtypenameについて
http://blog.wonderrabbitproject.net/2013/02/ctemplatetypename.html
• C++11の文法と機能(C++11: Syntax and Feature)
http://ezoeryou.github.io/cpp-book/C++11-Syntax-and-Feature.xhtml
• 一人ぼっちの共鳴 http://dos-sonority.jugem.jp/
• 今更人に聞けないプログラマ用語読み方いろいろ
http://dos-sonority.jugem.jp/?eid=1270
- 99.
- 100.