中3女子が狂える本当に気持ちのいい constexpr

58
中3女子 中3女子 が狂える が狂える 本当に 本当に 気持ちのいい 気持ちのいい constexpr constexpr Boost.勉強会 #8 bolero_MURAKAMI 2012/2/11

Upload: genya-murakami

Post on 28-May-2015

19.655 views

Category:

Technology


1 download

DESCRIPTION

Boost.勉強会 #8 中3女子が狂える本当に気持ちのいい constexpr

TRANSCRIPT

Page 1: 中3女子が狂える本当に気持ちのいい constexpr

中3女子中3女子が狂えるが狂える

本当に本当に 気持ちのいい気持ちのいい

constexprconstexpr

Boost.勉強会

#8bolero_MURAKAMI2012/2/11

Page 2: 中3女子が狂える本当に気持ちのいい constexpr

◆⾃⼰紹介•

名前

:

村上

原野

(むらかみ

げんや)

@bolero_MURAKAMI, id:boleros

棲息地:

⼤都会岡⼭

仕事

:

猪⾵来美術館

陶芸指導員・普段はやきものの修⾏をしたり、

縄⽂⼟器をつくったりしています・趣味は

constexpr

です

Page 3: 中3女子が狂える本当に気持ちのいい constexpr

◆⾃⼰紹介•

開催中:– 村上原野

縄⽂⼟器展

『ハロー、縄⽂!』〜2012/3/4

Page 4: 中3女子が狂える本当に気持ちのいい constexpr

◆⾃⼰紹介•

公開しているライブラリ:

Sprout C++ Library (constexpr

ライブラリ)github.com/bolero-MURAKAMI/Sprout

前回発表資料:【中3⼥⼦でもわかる

constexpr】

www.slideshare.net/GenyaMurakami

Page 5: 中3女子が狂える本当に気持ちのいい constexpr

◆アジェンダ•

はじめに

constexpr

おさらい•

constexpr

TMP の連携

(続)constexpr

レイトレーシング•

まとめ

Page 6: 中3女子が狂える本当に気持ちのいい constexpr

◆constexpr

とは?•

constexpr

宣⾔された変数は、コンパイル時定数になる

constexpr

宣⾔された関数やコンストラクタは、コンパ イル時にも実⾏時にも呼び出すことができる

リテラル型のオブジェクトは、コンパイル時定数にでき る

constexpr int always_zero() { return 0; } // constexpr 関数constexpr int compiletime_zero = always_zero(); // コンパイル時呼出int runtime_zero = always_zero(); // 実行時呼出

struct literal_type { }; // リテラル型のクラスconstexpr auto literal = literal_type{ }; // クラスインスタンスを定数式に

constexpr int zero = 0; // constexpr 変数using zero_t = std::integral_constant<int, zero>; // テンプレートにも渡せる

Page 7: 中3女子が狂える本当に気持ちのいい constexpr

◆constexpr

とは?•

constexpr

関数の制限

static_assert, typedef, using, 及び⾼々1つの

return ⽂のみ を書くことができる

引数は定数式にならない

template<class T>constexpr T square(T const& n) {

static_assert( true, “” );// static_assert( n != 0, “” );typedef T t1;using t2 = T;using std::ptrdiff_t;using namespace std;return n * n;

}

関数テンプレートもconstexpr

指定できる

Page 8: 中3女子が狂える本当に気持ちのいい constexpr

◆C++ プログラミングのレイヤー

プリプロセス時の世界(魔界)

コンパイル時の世界(ライブラリアンが多数棲息)

実⾏時の世界(⼈間界)

[プログラマのすること][処理されるもの]

ソースコードプリプロセッサ

メタプログラミング

テンプレートメタプログラミング型

実⾏時オブジェクト

定数式

通常のプログラミング

C++03

Page 9: 中3女子が狂える本当に気持ちのいい constexpr

◆C++ プログラミングのレイヤー

プリプロセス時の世界(魔界)

コンパイル時の世界(ライブラリアンが多数棲息)

実⾏時の世界(⼈間界)

[プログラマのすること][処理されるもの]

ソースコードプリプロセッサ

メタプログラミング

テンプレートメタプログラミング型

実⾏時オブジェクト

定数式

通常のプログラミング

C++11

constexpr

Page 10: 中3女子が狂える本当に気持ちのいい constexpr

◆C++ プログラミングのレイヤー

プリプロセス時の世界(魔界)

コンパイル時の世界(ライブラリアンが多数棲息)

実⾏時の世界(⼈間界)

[プログラマのすること][処理されるもの]

constexpr

ソースコードプリプロセッサ

メタプログラミング

テンプレートメタプログラミング型

実⾏時オブジェクト

定数式

通常のプログラミング

C++11

連携したい

Page 11: 中3女子が狂える本当に気持ちのいい constexpr

◆Sprout C++ Library•

constexpr

⽂字列

constexpr

タプル•

constexpr

バリアント

constexpr

アルゴリズム•

constexpr

範囲アルゴリズム

constexpr

コンテナ操作•

constexpr

乱数

constexpr

ハッシュ関数•

constexpr

UUID

constexpr

構⽂解析•

constexpr

レイトレーシング

Page 12: 中3女子が狂える本当に気持ちのいい constexpr

◆Sprout C++ Library•

constexpr

⽂字列

#include <sprout/string.hpp>#include <sprout/algorithm.hpp>

/* コンパイル時文字列 */static constexpr auto hello = sprout::to_string("Hello,world!");static_assert( hello == "Hello,world!", "" );

/* 文字列連結 */static_assert( hello + "!!!" == "Hello,world!!!!", "" );

/* 文字列切り出し */static_assert( hello.substr(0, 5) == "Hello", "" );

/* 文字列反転 */static_assert( sprout::reverse(hello) == "!dlrow,olleH", "" );

Page 13: 中3女子が狂える本当に気持ちのいい constexpr

◆Sprout C++ Library•

constexpr

⽂字列

このように、constexpr

で様々なクラスをとてもわかりやすく簡単に扱うことができる。

#include <sprout/string.hpp>#include <sprout/algorithm.hpp>

/* コンパイル時文字列 */static constexpr auto hello = sprout::to_string("Hello,world!");static_assert( hello == "Hello,world!", "" );

/* 文字列連結 */static_assert( hello + "!!!" == "Hello,world!!!!", "" );

/* 文字列切り出し */static_assert( hello.substr(0, 5) == "Hello", "" );

/* 文字列反転 */static_assert( sprout::reverse(hello) == "!dlrow,olleH", "" );

Page 14: 中3女子が狂える本当に気持ちのいい constexpr

◆constexpr

TMP の連携•

クラステンプレートにコンパイル時定数

を渡すには•

index_tuple

idiom

型⽂字列と

constexpr

⽂字列の相互変換

Page 15: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

整数型を渡すtemplate<int W, int H> RectArea {

static constexpr int value = W * H;};static constexpr int w = 50;static constexpr int h = 100;static_assert( RectArea<w, h>::value == 5000, “” )

Page 16: 中3女子が狂える本当に気持ちのいい constexpr

template<int W, int H> RectArea {static constexpr int value = W * H;

};static constexpr int w = 50;static constexpr int h = 100;static_assert( RectArea<w, h>::value == 5000, “” )

◆クラステンプレートにコンパイル時定数を渡すには

整数型を渡す 整数型はテンプレート引数にそのまま渡せる

Page 17: 中3女子が狂える本当に気持ちのいい constexpr

struct Rect { int w; int h; };

template< ??? >struct Area {

static constexpr int value = ???;};

◆クラステンプレートにコンパイル時定数を渡すには

整数型以外のオブジェクトを渡すには?

Page 18: 中3女子が狂える本当に気持ちのいい constexpr

struct Rect { int w; int h; };

template< ??? >struct Area {

static constexpr int value = ???;};

◆クラステンプレートにコンパイル時定数を渡すには

整数型以外のオブジェクトを渡すには?

テンプレート引数をどう書けばいい?

このクラスのインスタンスをテンプレートに渡したい

Page 19: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

クラスを直接テンプレート引数にしてみるtemplate<Rect V>struct Area {

static constexpr int value = V.w * V.h;};

static constexpr Rect rect = {10, 20};static_assert( Area<rect>::value == 200, “” );

Page 20: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

クラスを直接テンプレート引数にしてみる

クラス型をテンプレート引数にすることはできない•

論外

template<Rect V>struct Area {

static constexpr int value = V.w * V.h;};

static constexpr Rect rect = {10, 20};static_assert( Area<rect>::value == 200, “” );

コンパイルエラー!!

Page 21: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

ポインタをテンプレート引数にしてみるtemplate<Rect const* P>struct Area {

static constexpr int value = P->w * P->h;};

static constexpr Rect rect = {10, 20};static_assert( Area<&rect>::value == 200, “” );

Page 22: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

ポインタをテンプレート引数にしてみる

ポインタ型をテンプレート引数にすることは可能

template<Rect const* P>struct Area {

static constexpr int value = P->w * P->h;};

static constexpr Rect rect = {10, 20};static_assert( Area<&rect>::value == 200, “” );

OK!

Page 23: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

ポインタをテンプレート引数にしてみるtemplate<Rect const* P>struct Area {

static constexpr int value = P->w * P->h;};

int main() {static constexpr Rect rect = {10, 20};static_assert( Area<&rect>::value == 200, “” );

}

Page 24: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

ポインタをテンプレート引数にしてみる

テンプレート引数に渡せる値–

整数型

/ リンケージを持つオブジェクト

ローカル変数、⼀時オブジェクト、⽂字列リテラル等を テンプレート引数に渡すことはできない

template<Rect const* P>struct Area {

static constexpr int value = P->w * P->h;};

int main() {static constexpr Rect rect = {10, 20};static_assert( Area<&rect>::value == 200, “” );

}

コンパイルエラー!!

Page 25: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

プロキシクラスをテンプレート引数にしてみるtemplate<class Proxy>struct Area {

static constexpr int value = Proxy()().w * Proxy()().h;};

int main() {static constexpr Rect rect = {10, 20};

struct proxy {constexpr Rect const& operator()() const { return rect; }

};static_assert( Area<proxy>::value == 200, “” );

}

Page 26: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

プロキシクラスをテンプレート引数にしてみる

短所–

プロキシクラスをいちいち定義しなければならない

template<class Proxy>struct Area {

static constexpr int value = Proxy()().w * Proxy()().h;};

int main() {static constexpr Rect rect = {10, 20};

struct proxy {constexpr Rect const& operator()() const { return rect; }

};static_assert( Area<proxy>::value == 200, “” );

} OK!

proxy クラスの

operator() はローカル変数の

Rect

を返す

プロキシを介して値を取得

Page 27: 中3女子が狂える本当に気持ちのいい constexpr

◆クラステンプレートにコンパイル時定数を渡すには

ポインタをテンプレート引数にする⽅法

リンケージを持つオブジェクト(グローバル変数)しか渡すこと ができない

プロキシクラスをテンプレート引数にする⽅法

その都度プロキシクラスを作成する必要がある–

(プロキシの定義をマクロにすれば多少書きやすいかも)

template<Object const* P>struct TemplateClass;

template<class Proxy>struct TemplateClass;

Page 28: 中3女子が狂える本当に気持ちのいい constexpr

◆index_tuple

idiom•

index_tuple

index_range

ヘルパ

template<ptrdiff_t... Indexes>struct index_tuple;

template<ptrdiff_t First, ptrdiff_t Last>struct index_range;

static_assert( std::is_same<index_range<0, 5>::type,index_tuple<0, 1, 2, 3, 4>>::value, “” );

Page 29: 中3女子が狂える本当に気持ちのいい constexpr

◆index_tuple

idiom•

index_tuple

index_range

ヘルパ

template<ptrdiff_t... Indexes>struct index_tuple;

template<ptrdiff_t First, ptrdiff_t Last>struct index_range;

static_assert( std::is_same<index_range<0, 5>::type,index_tuple<0, 1, 2, 3, 4>>::value, “” );

パラメータパックをpack expansion expression

(Indexes...) で使う

(First .. Last] のindex_tuple

を⽣成するヘルパメタ関数

Page 30: 中3女子が狂える本当に気持ちのいい constexpr

◆index_tuple

idiom•

TMP で

index_tuple

を使う

#include <sprout/index_tuple.hpp>#include <boost/mpl/vector.hpp>

template<class Seq, class IndexTuple>struct to_tuple_impl;template<class Seq, ptrdiff_t... Indexes>struct to_tuple_impl<Seq, index_tuple<Indexes...> > {

typedef tuple< mpl::at_c<Seq, Indexes>... > type;};/* MPLシーケンスから

tuple への変換 */template<class Seq>struct to_tuple : to_tuple_impl<

Seq,typename index_range<0, mpl::size<Seq>::value>::type

> { };

typedef mpl::vector<int, double> vec;static_assert( is_same<to_tuple<vec>::type, tuple<int, double> >::value, “” );

Page 31: 中3女子が狂える本当に気持ちのいい constexpr

#include <sprout/index_tuple.hpp>#include <boost/mpl/vector.hpp>

template<class Seq, class IndexTuple>struct to_tuple_impl;template<class Seq, ptrdiff_t... Indexes>struct to_tuple_impl<Seq, index_tuple<Indexes...> > {

typedef tuple< mpl::at_c<Seq, Indexes>... > type;};/* MPLシーケンスから

tuple への変換 */template<class Seq>struct to_tuple : to_tuple_impl<

Seq,typename index_range<0, mpl::size<Seq>::value>::type

> { };

typedef mpl::vector<int, double> vec;static_assert( is_same<to_tuple<vec>::type, tuple<int, double> >::value, “” );

◆index_tuple

idiom•

TMP で

index_tuple

を使う

index_tuple<Indexes...> でテンプレート引数を特殊化する

pack expansion expression でIndexes を使ったリストに展開する

index_range

index_tuple

を⽣成して実装に丸投げ

Page 32: 中3女子が狂える本当に気持ちのいい constexpr

◆index_tuple

idiom•

constexpr

関数で

index_tuple

を使う

#include <sprout/index_tuple.hpp>#include <sprout/array.hpp>

template<class T, size_t N, ptrdiff_t...Indexes>constexpr array<T, N> to_array_impl(T const (& arr)[N], index_tuple<Indexes...>) {

return array<T, N>{{ arr[Indexes]... }};}/* 生配列から sprout::array への変換 */template<class T, size_t N>constexpr array<T, N> to_array(T const (& arr)[N]) {

return to_array_impl(arr, typename index_range<0, N>::type());}

static constexpr int arr[2] = { 1, 2 };static constexpr array<int, 2> s = to_array(arr);

Page 33: 中3女子が狂える本当に気持ちのいい constexpr

◆index_tuple

idiom•

constexpr

関数で

index_tuple

を使う

#include <sprout/index_tuple.hpp>#include <sprout/array.hpp>

template<class T, size_t N, ptrdiff_t...Indexes>constexpr array<T, N> to_array_impl(T const (& arr)[N], index_tuple<Indexes...>) {

return array<T, N>{{ arr[Indexes]... }};}/* 生配列から sprout::array への変換 */template<class T, size_t N>constexpr array<T, N> to_array(T const (& arr)[N]) {

return to_array_impl(arr, typename index_range<0, N>::type());}

static constexpr int arr[2] = { 1, 2 };static constexpr array<int, 2> s = to_array(arr);

index_tuple<Indexes...>を引数にして推論させる

pack expansion expression でIndexes を使ったリストに展開する

index_range

index_tuple

を⽣成して実装に丸投げ

Page 34: 中3女子が狂える本当に気持ちのいい constexpr

◆index_tuple

idiom•

index_tuple

イディオムは、インデックスアクセス可能

なデータ構造⼀般に適⽤できる–

配列

タプル–

ランダムアクセスイテレータ

型リスト

constexpr

に限らず、通常の関数や

TMP にも同じよう に応⽤できる

ただしインデックスアクセス不可なデータ構造には適⽤ できない

⾮ランダムアクセスなイテレータなど

Page 35: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

型⽂字列

⽂字列は可変⻑テンプレート引数で表現される–

⽂字列リテラルは使えない

(マクロの⿊魔術を使えば制限付きで可能ではある)

constexpr

⽂字列

コンパイル時定数である–

⽂字列リテラルが使⽤可能

これらを相互に変換できるようにしたい

typedef mpl::string< ‘Hell’, ‘o,wo’, ‘rld!’ > hello_t;

static constexpr auto hello = sprout::to_string( “Hello,world!” );

Page 36: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

mpl::string

sprout::string

#include <type_traits>#include <sprout/index_tuple.hpp>#include <sprout/type.hpp>#include <sprout/string.hpp>#include <sprout/type/boost/mpl/string.hpp>

using namespace std;using namespace sprout;namespace mpl = boost::mpl;namespace types = sprout::types;

Page 37: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

mpl::string

sprout::string/* T::value がナル文字であるか返すメタ関数クラス

*/

struct is_nul {template<class T, class = void>struct apply : false_type { };template<class T>struct apply<T, typename enable_if<T::value == 0>::type>

: true_type{ };

};/* ナル文字までの文字列長 */template<class Seq>struct str_length : types::distance<

typename types::begin<Seq>::type,typename types::seq::find_if<Seq, is_nul>::type

> { };

Page 38: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

mpl::string

sprout::stringtemplate<class Seq, ptrdiff_t... Indexes>constexpr sprout::basic_string<

typename Seq::value_type,str_length<Seq>::value

> to_sprout_string_impl( index_tuple<Indexes...> ) {return sprout::make_string_as<typename Seq::value_type>(

types::tuple_element<Indexes, Seq>::type::value...);

}/* sprout::string に変換 */template<class Seq>constexpr sprout::basic_string<

typename Seq::value_type,str_length<Seq>::value

> to_sprout_string() {return to_sprout_string_impl<Seq>(

typename index_range<0, str_length<Seq>::value>::type());

}

Page 39: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

mpl::string

sprout::stringtemplate<class Seq, ptrdiff_t... Indexes>constexpr sprout::basic_string<

typename Seq::value_type,str_length<Seq>::value

> to_sprout_string_impl( index_tuple<Indexes...> ) {return sprout::make_string_as<typename Seq::value_type>(

types::tuple_element<Indexes, Seq>::type::value...);

}/* sprout::string に変換 */template<class Seq>constexpr sprout::basic_string<

typename Seq::value_type,str_length<Seq>::value

> to_sprout_string() {return to_sprout_string_impl<Seq>(

typename index_range<0, str_length<Seq>::value>::type());

}

Indexes

を使ってシーケンス要素の⽂字のリストに展開

index_tuple<Indexes...> を実装関数で受け取る

basic_string<Elem, Length>

index_range

index_tuple

を⽣成して実装に丸投げ

Page 40: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

mpl::string

sprout::string

⼀般に【型→値】の変換は⾃明に書ける(場合が多い)

typedef mpl::string< ‘foo’, ‘bar’ > type;static constexpr auto s = to_sprout_string<type>();static_assert( s == “foobar”, “” );

mpl::string

(型)からsprout::string

(コンパイル時定数)へ変換

Page 41: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

sprout::string

mpl::string

#include <type_traits>#include <sprout/index_tuple.hpp>#include <sprout/fixed_container.hpp>#include <sprout/string.hpp>#include <boost/mpl/string.hpp>#include <boost/preprocessor/cat.hpp>

using namespace std;using namespace sprout;namespace mpl = boost::mpl;

Page 42: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

sprout::string

mpl::stringtemplate<class Proxy>struct to_mpl_string {

template<class IndexTuple>struct impl;template<ptrdiff_t... Indexes>struct impl<index_tuple<Indexes...> > {

typedef mpl::string<sprout::begin(Proxy()())[Indexes]...

> type;};/* mpl::string に変換 */typedef class impl<

typename index_range<0, sprout::size(Proxy()())>::type>::type type;

};

Page 43: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

sprout::string

mpl::stringtemplate<class Proxy>struct to_mpl_string {

template<class IndexTuple>struct impl;template<ptrdiff_t... Indexes>struct impl<index_tuple<Indexes...> > {

typedef mpl::string<sprout::begin(Proxy()())[Indexes]...

> type;};/* mpl::string に変換 */typedef class impl<

typename index_range<0, sprout::size(Proxy()())>::type>::type type;

};

Indexes

を使ってシーケンス要素の⽂字のリストに展開

index_tuple<Indexes...> を実装メタ関数で受け取る

mpl::string<Elem...>

index_range

index_tuple

を⽣成して実装に丸投げ

Page 44: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

sprout::string

mpl::string

/* 変換結果を typedef するマクロ*/#define STRING_CLASS_TYPEDEF(SOURCE, TYPE) ¥struct BOOST_PP_CAT(PROXY_, __LINE__) { ¥

constexpr typename remove_reference<decltype(SOURCE)>::type ¥operator() () const { return SOURCE; } ¥

}; ¥typedef typename to_mpl_string< ¥

BOOST_PP_CAT(PROXY_, __LINE__) ¥>::type TYPE

Page 45: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

sprout::string

mpl::string

/* 変換結果を typedef するマクロ*/#define STRING_CLASS_TYPEDEF(SOURCE, TYPE) ¥struct BOOST_PP_CAT(PROXY_, __LINE__) { ¥

constexpr typename remove_reference<decltype(SOURCE)>::type ¥operator() () const { return SOURCE; } ¥

}; ¥typedef typename to_mpl_string< ¥

BOOST_PP_CAT(PROXY_, __LINE__) ¥>::type TYPE

PROXY_127 のような名前のプロキシクラスが定義される

operator() は変換元ソースをそのまま返す

constexpr

関数

定義したプロキシクラスを渡す

Page 46: 中3女子が狂える本当に気持ちのいい constexpr

◆型⽂字列と

constexpr

⽂字列の相互変換

sprout::string

mpl::string

【値→型】の変換は⼯夫次第で可能•

⽋点–

⾃明な書き⽅ができない(場合が多い)

プロキシクラスの定義が必要な場合、インラインに書けないし、 constexpr

関数の中で使えない

#include <boost/mpl/equal.hpp>

static constexpr auto s = sprout::to_string( “foobar” );STRING_CLASS_TYPEDEF(s, type);static_assert( mpl::equal< type, mpl::string<'foo', 'bar'> >::value, “” );

sprout::string

(コンパイル時定数)からmpl::string

(型)へ変換

Page 47: 中3女子が狂える本当に気持ちのいい constexpr

◆constexpr

TMP の連携•

整数型以外のコンパイル時定数でも、テンプ

レートに受け渡す⽅法はある

index_tuple

イディオムや、プロキシクラス等 を活⽤することで、constexpr

TMP の間で

相互にやりとりをすることができる

Page 48: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• Sprout.Darkroom

metatrace

という

TMP ライブラリを元にした

constexpr

レイ トレーサーライブラリ

Page 49: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• 2つの球(Boost.勉強会#7 東京時点)

Page 50: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• 鏡の部屋の2つの球

Page 51: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• 鏡の部屋の2つの球(市松模様の床)

Page 52: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• 地球のような何か

Page 53: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• エレメント(カラーやスペキュラ)を表現するには

template<typename Element, typename Scale>class plaid_element {private:

Element elem1_;Element elem2_;Scale scale_;template<typename Unit>constexpr Element calc_1(Unit const& u, Unit const& v) const {

return (u >= 0 && v >= 0) || (u < 0 && v < 0)? elem1_ : elem2_;

}public:

template<typename Unit>constexpr Element operator() (Unit const& u, Unit const& v) const {

return calc_1((u < 0 ? scale_ + fmod(u, scale_) : fmod(u, scale_)) - scale_ / 2,(v < 0 ? scale_ + fmod(v, scale_) : fmod(v, scale_)) - scale_ / 2);

}};

Page 54: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• エレメント(カラーやスペキュラ)を表現するには

template<typename Element, typename Scale>class plaid_element {private:

Element elem1_;Element elem2_;Scale scale_;template<typename Unit>constexpr Element calc_1(Unit const& u, Unit const& v) const {

return (u >= 0 && v >= 0) || (u < 0 && v < 0)? elem1_ : elem2_;

}public:

template<typename Unit>constexpr Element operator() (Unit const& u, Unit const& v) const {

return calc_1((u < 0 ? scale_ + fmod(u, scale_) : fmod(u, scale_)) - scale_ / 2,(v < 0 ? scale_ + fmod(v, scale_) : fmod(v, scale_)) - scale_ / 2);

}};

市松模様を表現するエレメント

座標を⼆つに分けてどちらかのエレメント(⽩/⿊など)を返す

エレメントのコンセプトはuv

座標を受け取って結果を返す operator()(u, v) を持つこと

Page 55: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• テクスチャマップを読み込むには

– earth.png

#include <sprout/darkroom.hpp>

/* ファイル

"earth.tex.hpp" の内容を tex に読み込む */

#define DARKROOM_DEF_LOAD_TEXTURE_IDENTIFIER tex#define DARKROOM_DEF_LOAD_TEXTURE_FILE "earth.tex.hpp"#include DARKROOM_LOAD_TEXTURE

Page 56: 中3女子が狂える本当に気持ちのいい constexpr

◆(続)constexpr

レイトレーシング• テクスチャマップを読み込むには

– 擬似コード

#include <sprout/darkroom.hpp>

/* ファイル

"earth.tex.hpp" の内容を tex に読み込む */

#define DARKROOM_DEF_LOAD_TEXTURE_IDENTIFIER tex#define DARKROOM_DEF_LOAD_TEXTURE_FILE "earth.tex.hpp"#include DARKROOM_LOAD_TEXTURE

/* 実装は include ディレクティブで

CVS を取りこむトリックと同じような感じ

*/

constexpr auto tex {# include "earth.tex.hpp"};

“earth.tex.hpp”

の中⾝はコンマ区切りのピクセルデータのようなもの

Page 57: 中3女子が狂える本当に気持ちのいい constexpr

◆まとめ•

constexpr

を活⽤することで、『型』

『オブジェクト』『外部データ』等さま ざまなソースを、コンパイル時に相互に 扱うことができる

constexpr

でもっともっと遊ぼう!!

Page 58: 中3女子が狂える本当に気持ちのいい constexpr

ご清聴ご清聴 ありがとうありがとう ございましたございました