C++/TemplateMetaProgramming
1 :
デフォルトの名無しさん :
2008/02/16(土) 12:45:02 ・ここはC++のテンプレートメタプログラミング専用スレです。 ・なかったので立てました。 ・前にもあったような気がするけど気にしない。 ・次期C++(0x) boost STLの話題も、TMPに関係するならここにどうぞ。 仲良く使ってね。
とりあえずTMP始めてだから優しくしてね><って人には p_stabeのとこのブログのログを最初から読んだりしてみる事から始めるといい。
3 :
デフォルトの名無しさん :2008/02/16(土) 12:49:15
すいません、やっぱり、該当スレでお願いします。 申し訳ありませんでした。
おい
>>1 、メタだけあってもしょうがないだろ
何を話題にすりゃいいんだ
>>4 template<fugafuga>を使った機能とか、
必要であればプリプロセッサも絡めてもらうとありがたいです。
>>7 だったらテンプレートスレにしておけば良かったのでは・・・
なぜメタ限定?
>>8 テンプレートスレならNTPとかMOJOばっかりで
Lispみたいなメタプログラミングは話題にし辛いだろう。
ここはそういうのを扱うスレ。コンパイル時点での、コードに対するプログラミングに関するスレ。
10 :
デフォルトの名無しさん :2008/02/16(土) 12:59:04
>>8 激しく同意だな
でも、テンプレートスレじゃboost、STL、C++スレでカバーで良いんじゃね
とりあえずPreprocessor Metaprogramming万歳
メタプロと普通のテンプレート使ったプログラムは全然違うだろう。
STLスレやboostスレとか何度も統廃合の話題が出てその度に荒れていたな
スレが立った初っ端からいろいろ文句つけてる奴は何だ? 現在、板の各所に散らばっている“テンプレートスレ”で満足しているならこんな所覗く必要はないだろう。 “メタプログラミング”を話題にしたい奴がここを必要としているんだ。興味がないなら来るな。
そうだそうだ
いや、興味あるとかないとかそういう問題じゃねぇーだろw
別にMetaProgrammingであればTemplateは必要なかったのでは?
誤解を招くだけだし。
あと、
>>1 >仲良く使ってね。
メタプロが理解できない奴が嫉妬してクレーム付けてるだけだろ
勢いが1234もある。 過疎ったVIPスレ並みに速い流れだな。その割には糞なレス多いけど。
{ std::ofstream f( "tmp.cpp" ) ; f << いろいろいろいろいろいろ ; } system( "cc tmp.cpp" ); system( "a.out" ); では、このあたりからw
クラックしがいがありそうだなw
>>20 テンプレート(ライブラリ)を使ったメタプログラミングだwww
23 :
デフォルトの名無しさん :2008/02/16(土) 13:15:15
だいたい、
>>1 がアホだからいけないんだ
Templateなんて入れるないで、素直にC++/メタプログラミングすればよかった
>8 Boost, STLとの統合の話題が出てくるからじゃね? あっちは使い方、こっちは実装テクニックと使い分けできるといいね。 そういやポリシーってみんなどんぐらい使ってる? template<class T> class M : public T {}; struct T1 { void t1() {}; }; struct T2 { void t2() {}; }; M<T1>().t1(); M<T2>().t2(); とか、インターフェースの差し替えが出来てけっこう便利な気がするんだけど。
単純にテンプレートテクニックスレで良かったんじゃね、とか
>>24 スーパークラスに直接Tをいれるのはコンパイルが異様に重くなるので最近は避けているな。
28 :
24 :2008/02/16(土) 13:27:07
>27 エエエ(ry コンパイルなんて昔に比べると激早だから、あんまり気にしないなあ。 どちらかというと使う側でpimplとかの工夫してるし。
そおか、C++以外の言語を使ったあとだと余りの遅さにかなりショックを受けるんだが。
100ファイル程度あると、C++は自作オーバークロックの最強マシンをもってして三十分や一時間かかりかねないけれど これがC#だとヘナチョコマシンでも一分掛かるか掛からないかといった所。
コンパイル時間のほとんどは プリプロセスなんだろうなあ。
>>30 どう考えてもそれは長すぎる
せいぜいかかっても1ファイルに2〜3秒ってところじゃないの?
Boost.Lambdaのヘッダをプリコンパイルドヘッダに入れようとすると、 pchがぶくぶく膨らんでいく。 後のコンパイルでは、プリコンパイルドヘッダの読込も ボトルネックになっているのではという気がしてならない。
プリコンパイルでどれだけの時間が短縮されるか考えたら そんなもんだと思う
プリコンパイルは一応コンパイルもしてるわけで
>33 ヘッダを重くするとそうなるけど、それこそpimplで隠したら? Boost.Lambdaをヘッダに突っ込もうとする時点で何か設計で失敗している気がするけど。 #ライブラリを設計しているのならしょうがないけど
$ cat test.cpp # include <boost/lambda/lambda.hpp> int main() { using namespace boost::lambda; int i = 4; return (_1 + _1 + 1)(i); } $ time g++ test.cpp real 0m1.175s user 0m0.900s sys 0m0.068s $ time cpp test.cpp >/dev/null real 0m0.249s user 0m0.160s sys 0m0.024s
>>37 たしかにLambda自体は特定のcppファイルでしか使っていない。
こういうときはプリコンパイルドヘッダから外すべきなのか?
そらそうだな。
>39 ヘッダは基本的にインターフェイスなんだから、インターフェイスに不要な実装は隠すのが望ましい。 テンプレート使ってるとそんなことも言ってらんないけど。
そろそろC++という言語自体を見直すのが望ましいという気もしないでもない 問題累積しすぎだろ
>>41 stdafx.hで何もかもインクルードしていたよ。
ある程度確定したクラス他は専用libに放り込んでるので無問題
・クラス単体のみの宣言だけ class A; ・クラスのインターフェイスを含めた宣言だけ class A{ void f(); }; 2種類のヘッダを用意すれば(ry
>41 C++狂Herb Sutterの本を読んだほうが良いと思う。 ヘッダファイル: インターフェイスに関係するファイルを最低限 ソースファイル: できるだけこっちでインクルードする が基本だよ。
コンパイル時間の節約は分かるんだが、 いざヘッダファイルをインクルードして何か使おうとすると 実装が無いとか文句言われることがあるのが困るんだよな。
実装じゃねえや。定義だ。
>>48 ただの誤用にしか聞こえんのだが、どういう状況の話?
不完全型のみで十分な状況では その型を定義してあるヘッダをインクルードせず、 不完全型の宣言のみを書く。 そして、その型を使ってるソースファイルでのみ、 そのヘッダファイルをインクルードする。
なんかC++の基本もまともに出来ないような人が居ますね。
TMPやるにはHaskell勉強した方が良いって本当ですか?
>>53 変数への代入ができないという制約の下でどうやって問題を解決するかを学ぶ、
という点で本当だと思う。
SICP読んだらModern C++ Designが分かった
Scheme勉強したらModern C++ Designが分かった
あれって別の関数型言語を勉強してからじゃないと理解できないほど難しいか?
ムチャクチャな書き方をしないといけないからわかりにくいんだよ。 すっきりした表記の関数型言語を勉強した後だと どういうトリックなのかがすんなり理解できる。
別に無茶苦茶ではないと思うが。
再帰に継承が絡んでくると難しく感じる。
慣れてないだけだな。それにあんなもの別にC++以外のものを触ったって慣れやしない。
ところで
>>2 のp_stabeには誰もつっこまないの?
p_stadeじゃないかって
q_stabe
>>61 それは違うと思う。関数型言語のほうが記法が簡便だが抽象度が高く
センスが必要。LispでもSchemeでも自在に扱えればC++のメタなんて少し
の時間でマスターできる。templateなんて少しの時間でマスターできる。
経験上確信してる。逆は成立しない。
千差万別、十人十色 自論に固執すること愚か也
言語に組み込まれてるってのは重要だよな。 C++だとマクロとかでちょっと文法の解釈を脳内変換すれば いいんだけど手間が増大するのと 初学者に扱える代物ではなくなってしまうんだよね。
負けへん、負けへん 山ちゃんは負けへんでええ
誰か質問しろよ。 スレ落ちるの時間の問題だな。
C++0xではmplは入らなくてTypeTraitsどまりってことは mplはまだ重視されてないってこと?メイヤーズの本では TMPがC++の中心に来ることはないなんて書いてあったけど どうなんだろ?
そうなんでしょう。 だって頭の体操にはなるけど、あんまり実用性ないじゃん。
73 :
デフォルトの名無しさん :2008/02/18(月) 19:27:11
type_traitsはフレームワークであって、 みんなが自分のクラスのtraitsを提供しないと真価を発揮しないけど、 mplは使いたい人が使えばいいだけだから標準化しなくても困らない。
C++0x において提案されている <type_traits> で提供される機能の中には コンパイラが持っている独自の情報を吐いてくれないと実装できないものも多いので そういう意味で TypeTraits は優先的に規格として明示してくれないと困るかと
call_traits は追加されるの?
MP専用の構文を入れる気はもうないのかね Templateでできたのはたまたまであって、 いつまでもあんなハックみたいな書き方したくないなぁ
バッドノウハウ
完全体のC++かどうかを判断するために compiler_traits が必要な気がする。
そうなるとまず has_compiler_traits が必要だな。
いやあ、すべってるねえ このスレ
昔ProgramingJemsにメタプログラミングでsinテーブルを生成するっていうネタがあった 当時メタプログラミングなんて知らなくて、 「すげぇぇぇぇ」と感動して自分でも作ってみた しかし当時のオレのショボマシンではコンパイル時のサインテーブルの生成に結構な時間がかかり 最終的に、 Perlでテーブル書いたソースジェネレートした方が早くね? という結論に
メタプログラミングとは? テンプレート、型、typedef、コンパイル時定数、再帰を 駆使したコンパイル時プログラミングで合ってる?
テンプレートメタプログラミングならそれでまあ合ってる。
>>83 それはテンプレートメタプログラミングの説明だな
メタプログラミング自体はもっと広く、プログラムを操作するプログラム全般をいう
プリプロセッサを使うのもメタプログラミングだし、コードジェネレータを書くのも含む
テンプレート抜けてた。
そういう意味では82のPerlでソース生成と言うのも立派なメタプログラミング。
>>82 そんなあなたに constexpr@C++0x
一方D言語はsinを定数として畳み込んだ。
静的に実行できる関数は静的に実行してしまう。 D は中々のものだ。
D言語って誰が生みの親なの?
昔borlandで働いてた人
をるたん
ボーランドはちがくね?
>>82 まあC++のテンプレートはメタプログラミングのために設計されてないからねえ。
マクロらしいマクロを持った言語なら、かなり高度なメタプログラミングをやってても
普通のコードの2倍やそこらの時間でコンパイルできる。
Lispの世界じゃ40年前からメタプログラミングが当たり前だし、
DOSの世界ではMASMのマクロで構造化なんてのが流行った。
ライブラリ作るときは主流になりそうだけどな。 てか、もうなってるか。 でもschemeのほうが言語機能としてcons listとか があるから、より簡潔でストレス感じない。 C++のTMPはいかんせん表現がキモ過ぎる。
そこで constexpr ですよ
こんなの作ってみた。 自分のプログラムでは活用できてるからいいんだけど、意外と汎用性ないな…… struct UniqueNumber { template<class type_t> static unsigned int number() { static unsigned int n(count()); return n; }; private: static unsigned int count() { static unsigned int c(0); return c++; }; }
>>83 プログラムを作るプログラムをプログラムしてみようって事だよ
当然、(プログラムをつくるプログラム)をつくるプログラムもね。
どこまででも逝ってくれ
>>99 typeidの速度が気になる場面で使うのかな?
>>99 struct UniqueNumber {
static unsigned int number() { return count(); }
private:
static unsigned int count() { static unsigned int c; return c++; }
}
これでよくない?
>>103 何で?
type_tテンプレートパラメータ使われてないよ。
>>104 UniqueNumber::number<A>()とかUniqueNumber::number<B>()みたいな使い方するんでしょ。
で、テンプレートに渡した型毎に一定のユニークな値が返ってくると。
ああそうか でも cout << UniqueNumber::number<int>() << endl; cout << UniqueNumber::number<int>() << endl; cout << UniqueNumber::number<int>() << endl; cout << UniqueNumber::number<char>() << endl; cout << UniqueNumber::number<char>() << endl; cout << UniqueNumber::number<float>() << endl; やったら 0 0 0 1 1 2 となった。 何で、0 1 2 0 1 0にならないのかな?
107 :
106 :2008/02/25(月) 17:38:05
わかりますた。なるほど。
108 :
99 :2008/03/01(土) 03:50:23
ちょっと質問です。 外部リンケージについて詳しく書いてある解説ってある? 具体的には関数内クラスをテンプレートパラメーターにして渡したいんだけどね。 externでも上手く行かんし……
それはそもそも無理じゃまいか?
111 :
106 :2008/03/15(土) 22:19:26
112 :
デフォルトの名無しさん :2008/04/10(木) 23:41:05
メタプログラミングしてると脳汁でます
なぜjavaやC#でtemplateが外されたか 不要物だからw
なぜJavaやC#でgeneri(ry
失ってから大切さに気付くものです
116 :
デフォルトの名無しさん :2008/05/07(水) 22:32:52
boost::mplとか使ってるコードで見る、 _1, _2ってどうやって実現してるんですか?
ソース読めばいいだろw
defineかtypedefだったかな
テンプレートで配列指定された場合エラーにする方法ってあるんでしょうか?
type_traitsのis_arrayとBOOST_STATIC_ASSERTを組み合せればいけるはず
121 :
:2008/05/14(水) 07:27:15
g++とVC2008どっちがテンプレート学ぶにはいいですか? どっちがより完璧にテンプレートをコンパイルできますか?
どうみてもg++
123 :
:2008/05/14(水) 09:16:34
テンプレートの実体化でテンプレート引数を特殊化にマッチさせる過程って Prologの統一化と似てる気がする
>>99 のような型にユニークな数字を割り当てるのをコンパイル時にできないでしょうか?
boost::fusion::vectorに格納されている型をすべてユニークな型にしたいとき、
単純に片っ端から同じ型が含まれていないか調べると計算量がO(n*n)(nは格納されている型の数)になるかと思います。
そこで、boost::fusion::vectorをboost::mpl::sortしてboost::mpl::uniqueすれば
sortが平均O(n*log(n)), uniqueがO(n)だとすると先に説明した単純な方法より高速に計算する事ができるかと思います。
ですが一般的な型に対して順序関係はないのでboost::mpl::sortを実行することができません。
そこで
>>99 のような型毎に静的にユニークな数字を割り当ててboost::mpl::sortを適応させることができるようにしたいです。
長くなりましたが、皆様宜しくお願いします。
ムリじゃない? 分割コンパイルみたいな局面を考えると、ある型にユニークな数字が割り当て済かどうかすら判らんと思う。 リンカと連携すればいいんだろうけど、C++の規格はそこまで考えてないんじゃない? 指定された型のstaticポインタを用意してそのアドレスを使えばなんとかなるかも知れんが、どうなんだろ? void*にキャストすれば比較もできるんじゃね?
そもそも数字の割り当て方を制御できないとソートする意味がなくね? どう割り当てたいの?
どんな数値でもいいから割り当ててしまえば二分探索の恩恵を受けられるってことだろ
>>126 やはり無理なんですかね。
アドレスを得られるのはコンパイルのテンプレートの展開等の後の段階になるので無理だと思うのですが。
>>127 >>125 で書いてある通り,型の集合の中に同じ型が含まれないようにすることが目的なので
boost::mpl::uniqueする前に同じ型が連続して並ぶようにboost::mpl::sortの結果が返ればよいのです。
ですので割り当てたい数字は型毎にユニークであれば何でもよいのです。アドレスもOK養豚場です。
>>128 二分探索を使って同じ型を消す処理をしてもO(n*log(n))で計算できそうですね。
そういう方法は考えていませんでした。
>>125 で書いた事をもう少しわかりやすく説明すると
例えば以下のような型があったとき、
typedef boost::fusion::vector<char, int, char, int> vec;
vecから重複する型を削除してユニークな型を保持するようにしたいのです。
typedef hoge<vec>::type unique_vec; //こんなhogeを欲しているのです.
BOOST_MPL_ASSERT(( boost::is_same<unique_vec, boost::fusion::vector<char, int> > ))
それで、以下の仮想コードのような方法を使とO(n*n)の計算時間が掛ります.
for i∈vec
for j∈vec
もしiとjが同じ型だったらjをvecからはずす.
そこで
typedef
boost::mpl::unique<
boost::mpl::sort<
vec, piyo>::type,
is_same<_1, _2> >::type
unique_vec;
とやればO(n*log(n))の計算量で済みます。
そこで上記のpiyoに相当するMetafunction class、
すなわち型に順序関係を与える方法を教えて貰いたいのです。
>>128 referenceにはboost::mpl::findは線形時間が掛ると書いてあるので
二分探索するには自分でコードを書かないといけないようです.
>>124 静的(コンパイル時完全評価)だけどな。
VIPのスレで昔テンプレートでアッカーマン関数の問題解こうとしてドツボにハマった奴がいた。
132 :
デフォルトの名無しさん :2008/07/16(水) 20:46:07
『Modern C++ Design―ジェネリック・プログラミングおよびデザイン・ パターンを利用するための究極のテンプレート活用術 (C++ In‐Depth Series) 』 ってのを読んでいる素人だけど、69ページのMostDerivedってのが マジ分からん。今日、朝、昼、晩を合計で4時間ぐらい考えたんだが どういう流れでこれで継承関係でいちばんの派生なのを特定できるのか 分からん。誰か分かる人いませんか?
133 :
デフォルトの名無しさん :2008/07/16(水) 21:05:22
結局、 typedef typename MostDerived<Tail, T>::Result Candidate; では、再帰的に展開が繰り返され、MostDerived<NullType, T>に なり、CandidateはTにしかなりえない 続く、 typedef typename Select< SUPERSUBCLASS(Candidate, Head), Head, Candidate >::Result ResultではCandidateはTと読み替えられるわけで TがHeadのスーパークラスなら結果はHead HeadがTのスーパークラスなら結果はTとなる これじゃ全然ダメじゃね? ググってみたけど、MostDerivedはダメだったって話を他でも見かけたよ
>133 >typedef typename MostDerived<Tail, T>::Result Candidate; >では、再帰的に展開が繰り返され、MostDerived<NullType, T>に >なり、CandidateはTにしかなりえない どの段階で T にしかなりえないと思ってるのか分からないけどちゃんと再帰的に展開できてる? MostDerived<TypeList<T0, TypeList<T1, NullType> >, T>::Candidate # Head=T0, Tail=TypeList<T1, NullType> →MostDerived<TypeList<T1, NullType>, T>::Result # Head=T1, Tail=NullType →Select<SUPERSUBCLASS(MostDerived<NullType, T>::Result, T1), T1, MostDerived<NullType, T>::Result>::Result # MostDerived<NullType, T>::Result → T →Select<SUPERSUBCLASS(T, T1), T1, T>::Result 結果として、 MostDerived<TypeList<T0, TypeList<T1, NullType> >, T>::Result →Select<SUPERSUBCLASS(Select<SUPERSUBCLASS(T, T1), T1, T>::Result, T0), T0, Select<SUPERSUBCLASS(T, T1), T1, T>::Result>::Result T と T1 を比較した結果、と T0 を比較した結果が返ってくる。
ttp://www.fides.dti.ne.jp/~oka-t/cpplab-tips-1.html に
ローカルクラスの静的関数は関数テンプレートの引数に指定可能というのがあるのですが、
ローカルクラスのクラス内クラスの場合どうなりますか?
役立たずVC8だとノーチェックでOKにしたので確認できませんでした。
void func() {
struct local {
void operator()(int x) { cout << x << endl; }
static void f( int x ) { cout << x << endl; }
struct func {
void operator()(int x) { cout << x << endl; }
};
};
std::vector<int> v;
v.push_back(0);
v.push_back(1);
v.push_back(2);
for_each( v.begin(), v.end(), local::f );
for_each( vbegin(), v.end(), local::func() ); // これはどうなるの?
for_each( v.begin(), v.end(), local() ); //ホントはエラーのはず。VC8.0はOK……
}
VCだと言語拡張を有効にすることで関数内構造体もテンプレート引数に渡せてしまう。 俺はそれが嫌で言語拡張を無効にしてる。
>136 サンクス。無効にすると両方ともNGになりますね。 言語拡張を無効にすると色々なライブラリが使い物にならなくなるから、 さすがにそこまでストイックにはなれないなぁ……
言語拡張機能が使用された場合に警告を出すってオプションがあったと 思うんで、取り合えずそれONにしとけば?
そんなもの存在しません。
140 :
デフォルトの名無しさん :2008/10/14(火) 17:41:25
工エエェェ(´д`)ェェエエ工工
template <template <class Created> class CreatePolicy> これのtemplate <class Create>部分の採用がヨクワカラナイ どこかに良い説明のってないっすか
とりあえず検索用語だけ template-template-parameters
class Hoge { template <int X> void Fuga() {...} }; テンプレート引数Xの値を、静的な値として集めることってできますか? 具体的には、呼び出されたFugaのうち、最も大きいXを取得して、別のクラステンプレートに渡すとか。
>>143 パッとみて無理っぽいうえにコンパイル単位をまたぐ場合を考えるとさらに無理っぽい。
(´;ω;`)
>>142 横だけど、meta templateでググっても見つからなく困っていたので助かった。
そういう用語だったのか…
147 :
99 :2009/01/12(月) 20:40:07
148 :
99 :2009/01/13(火) 00:44:59
ちょっとだけ >147を修正。 登録をヘルパークラスに任せることにしました。少しはスマートに見えるけど、受け入れる型を 全部登録しなきゃいけないのは変わらず…… 色々と考えてみたけど、どうやっても仮想関数に型情報は渡せなさそうね……。
149 :
99 :2009/01/13(火) 01:15:20
ポリシーによるプログラミングで質問です。 適当な乱数を発生させるTraitsクラスを何個か定義します。 struct r {int rdm(){return rand()%128;}}; struct rs{int rdm(){return rand()%7+60;}}; そんで、Traitsを使うクラスがこれ。ここまでは順調です。 template <class T=r> class R{int rdm(){return T.rdm();}}; この後、rdm関数が引数を持つようなTraitsを加えようとすると型があわないため困りました。 しかし、こういうケースは良くあるのではないかと思います。 struct rc{int rdm(int n){return n*(rand()%128);} 少し悩んでこんな解を出して見たのですが こういう場合、みなさんどのように解決されますか? template <int N> struct rt{int rdm(){return N*(rand()%128);} R<rt<3> > r; ↑この場合、途中で引数を変えたいと思った場合毎回インスタンスを作る必要がある点が若干面倒です。 また、整数引数しか使えません 関数でやる場合は引数変更は楽ですが Traitsにあたるものが増えてくると関数の組み合わせ爆発が大変です。 手法にこだわりはないのでこのやり方が楽、などあればきいてみたいです。
struct r{ int rdm(){ return rand() % 128; } }; struct rs{ int rdm(){ return rand() % 7 + 60 } }; template<typename Ty> struct rc{ Ty value; int rdm(){ return value * (rand() % 128); } }; 後はrc::valueのゲッター書くなりセッター書くなりしろ。
152 :
150 :2009/01/19(月) 21:33:25
STL コンテナでアロケータを指定する方法を真似するのは、何か都合が悪いの? template <class T=r > struct R { T t; R( const T & t_ = T() ) : t(t_) {} int rdm() { return t.rdm(); } }; R< random_with_number > rn( random_with_number(3) );
>>153 これは良いですね!頂きます。
使ってみて、若干罠というか、引数なし版はプロトタイプ宣言と勘違いされるため
R<r> a(r()); //error
こうする必要があるんですね(もっと良いやり方があるのかは知らないですが・・)
R<r> b(*(new r()));
これを参考に、少し書き換えて見ました
struct b {virtual int rdm(){return 0;}};
struct r:b {int rdm(){return rand()%128;}};
struct rs:b{int rdm(){return rand()%7+60;}};
struct rc:b{
int val;
rc(int n) : val(n){}
int rdm(){int tmp=rand()%7;if(tmp%val==0){return tmp;}else{return rdm();}}};
template <class T=b > struct Q {
T* t;
Q( T* t_) : t(t_){}
int rdm() { return t->rdm();}
};
Q<> a(new rc(3));
Q<> b(new r());
>>154 > R<r> a(r()); //error
R<r> a((r()));
でいけるよ
ほんとだ、こっちのが短くていいですね。
struct b::rdm() を virtual にするなら template にする意味は無いと思うのだけれども・・・。 struct Q { // non template version b * t; Q( b * const t_) : t( t_ ? t_ : new b ){} ~Q() { /* Do you want to delete t ? */ int rdm() { return t->rdm();} }; でいいでしょ。 ポインタじゃなくて、値のコピーのほうが、いろいろいいよ。
単に左辺を書かなくても良くなるぐらいの気持ちで書き直したんですが そもそもtenmplate無くても動きますね・・難しいなぁ ある意味、template使わなくてもポリシーベースのプログラミングが出来るわけですね あえてtemplateを使う利点が整理できてないので考えてみます。 >ポインタじゃなくて、値のコピーのほうが、いろいろいいよ。 シンプルながら、これは説得力ありますね
160 :
157 :2009/01/24(土) 17:11:30
>>158 > あえてtemplateを使う利点が整理できてないので考えてみます。
157 では、t->rdm() は、コンパイラによって必ず仮想関数呼び出しコードが出力される。
テンプレートバージョンでは、定数を返す場合などには、もしかしたらコードは全く無くなるかもしれない。
153 程度で大げさな、と思うかもしれないが、これもメタプログラミングだ。
実行時に通過するコードではなく、コンパイルで出力されるコードを、引数で変えることが出来るから。
C のプリプロセッサマクロでも出来るけど、C++ template は型チェックとそこから派生する特殊化された型の選択が強み。
> シンプルながら、これは説得力ありますね
157 の Q のデストラクタを見てみて。
あと、メモリ消費量が減るかも。
ところで、154 の記法の問題は、cl, bcc, gcc で試したけど、
R<r> a( (r)r() );
が一番互換性が高いようだ。
もちろん 159 でいいんだけどw 引数を明示したいならね。
> R<r> a( (r)r() ); たまたま‘r’という短い名前だからそれでいいかもしれんが、 名前が長かったり、さらにネストしたテンプレートクラスだったりすると 書くのも面倒だよ。 他にも R<r> a = R<r>(r()); とか考えられるけど、やっぱり R<r> a((r())); が楽だと思うけどね。
age
テンプレートの引数にテンプレート渡せるのか〜知らなかった。 これで大分やれることが広がったぜ。ウヒヒ ていうか、テンプレートの完全な仕様ってどこに行けばみれるの?
165 :
デフォルトの名無しさん :2009/04/06(月) 19:01:46
>>167 >う〜ん、そこからのリンクも切れてるなぁ。
これでリンクが切れてるなんて言うお前に、Modern C++ Design rokiは無理
Loki とroki さてどっちでしょう
>>165 には関係ない話題ですがww
流れを気にせず好き勝手に意見を述べるが 先に関数型を勉強してからMC++Dを読む方が すっきり理解出来る気がする 要は、既に確立した技術をC++に応用したわけだが このロシアおっさんのとんでもない所は 要素技術とでも言うべき箇所、 例えば...やらsizeofの評価順序やら型としてのstructやらを C++の仕様から見つけ出したところだと思うわ。 コンパイラが対応してない時代にどんだけ仕様把握してるんだよ パねぇっす 宇宙ヤヴァイの改変コピペが作りたくなるぐらい。
でもconceptがまともに使えるようになるまでC++でプログラミングしたくないよねーってなるよ
少年アシベで アイスをねだるゴマちゃんに 豆腐を与える静的なダックタイピング structuralなポリモフィズムのことだっけ? C++0xでたら考えよう。それまでは関数型で遊んでる ところで、ポリシーによるプログラミングが 綺麗に適用出来るケースって、結構少ない気がするんだ AがB/C/Dで代替出来るケースよりも AがA(B)やA(B(C))で代替とするケースのほうが プログラミングしてて多いように感じる
174 :
167 :2009/04/07(火) 03:26:42
>>171 たしかにlambdaとかbind(束縛)なんて単語に馴染みあるかないかでも理解スピードは
違うだろうな。
つかなんで無理やりC++でここまで頑張るのか不思議だ。
暇なんだろ
boostのlambdaは、確かに実用性に欠ける あれの意味不明なエラーメッセージと格闘してる暇があるなら 普通に関数オブジェクト作った方が早い
書いてる段階でエラーに気づかないほど複雑なものをboost::lambdaで書こうとするのが間違い。
そもそもC++で関数型をやるのが間違い
C++0x!はやくきてくれー!
永遠にこないでくれ by 製品コンパイラ開発者
その程度のコンパイラ開発者なら要らん。
そうです TMPは導入されたのではありません 発見されたのです!
185 :
デフォルトの名無しさん :2009/09/04(金) 17:57:25
テンプレートメタで仮想関数の有無を調べることは できないでしょうか? 今の知識では思い浮かばない・・
その関数がPOD型かどうかを見るよろし
関数がPODてなんじゃらほい。 クラスに仮想関数があるかどうかの話なら、boostのis_polymorphic ですね。チェック対象クラスを継承した2つの同等なローカルクラスを 用意。但し片方はvirtualデストラクタ付きにしといて、2つの sizeofの結果が同値なら元からvtbl付だった -> 仮想関数あった。
なるほどー。質問者じゃないけど勉強になった
MPLのスレとかあるのかなぁ、と思ってJaneのスレタイ検索窓に"MPL"と入れたら ここが候補に挙がって、一瞬ものすごいインテリジェントな検索機能に見えた
なるほど、teMPLateなのか。
191 :
デフォルトの名無しさん :2009/09/09(水) 13:08:44
なんでも出来るなC++
クラスに対してユニークなコンパイル時定数を割り振る方法ってある?
MPLでそんなことができたかも知れない
typeid(T) じゃだめ?
数年前typeof作れないかとそれやろうとしてたけど無理っぽかった。
C++0xでそんなことができたかも知れない
198 :
デフォルトの名無しさん :2009/09/17(木) 14:56:10
確率計算の為のクラスを造るとします 内部でリストを持ち 要素の連綿の登録後 この要素は何個あるとか確率はなんぼとか返せるように造ると しかし要素がペアだった時は同時確率を求められるようにしたいとします その為に内部ではリストでなくマップで持つとします k->v これで(3,6)は何個とか瞬時に返せます ここで困ったのです ペアのペアで要素登録すると (k1->v1)->(k2->v2)で管理するのでなく k1->k2->k3->vとして欲しいのです (1,8,4,3)は何個とか瞬時に返して欲しい TMPなら解決できますか? 必要な深度のメタマップクラスを造ってくれるんです
どっちかというと要素を専用のクラスにして、そのクラスのリストを持つべきなんじゃ?
>>193 staticメンバのアドレスを取るとか…
ああ、コンパイルタイム定数じゃないから駄目だな
202 :
99 :2009/09/19(土) 21:39:29
久しぶりにプログラム板見たら、こんなスレが出来ていたので少しびっくり、 map のハッシュ値からキー値を検索するようなアルゴリズムって無いのでしょうか? pair でmap へinsert した値を相互(キー値、ハッシュ値)で検索し合えれば 少し幸せになれるかと思いました、質問させてください、よろしく。
>>204 Thxです
流石boost いろいろそろってますね。
static const char* foo = "FOO"; これを static char* foo = "FOO"; このような型に変換したいのですが template を用いてconst 剥がしが出来ないでしょうか?
>>206 すでに変換できてるように見えるんだが、何がしたいんだって?
>>206 です
配列foo を、こんな感じで、使いたいんだけど、const が付いてると
first = foo;
ここで引っ掛かってコンパイルが通らないので、一時的にconst 剥がしが出来ないものかと、子一時間です。
template<class Iterator, class T>
Iterator search(T target)
{
static const char* foo = "FOO";
T* top;
T* first;
first = foo;
top = first;
〜省略〜
}
>>208 const_cast でコンパイルは通せるけど、書き込んじゃダメなのは変わらないんだから、
first に const 付ければいいんじゃないの?
>>208 です
>>209 なるほど
const T* top;
const T* first;
これで、いけました、処でまだconst 剥がしに拘るんだけど
template <class T>
struct remove_const {
typedef T type;
};
template <class T>
struct remove_const<const T> {
typedef T type;
};
こんなtemplate があったとしも、これでは
static const char* foo = "FOO";
この、const 剥がせません無いのですが、いい方法が無いんでしょうか?
それはconst_castの仕事でござるよ
const剥がしの目的にもよるが、面倒とかよく分からないとかいう理由で剥がすのは 危険だからちゃんと慣れるべき。Cでポインタ分からないままコーディングするのに 近いレベル。 constを剥がす正当な理由は、「const非対応な古いコードor糞コードと組み合わせ なきゃならない時に仕方なく」というもの。それはconst_castでやる。 const剥がしのキャストは一見大したこと無いけど、見た目よりは危険だから避ける べき。
メタ関数で階乗などの整数値を計算できるのは理解したんですが 円周率などの実数値を計算することはできないんでしょうか?
浮動小数の仕組みを思い出そう。
実数のような無限列はそもそもコンピュータでは扱えない。 浮動小数に近似するとしても、どこまで近似するかという問題があるから簡単には扱えんよ。
逆に、どこまで近似するか決めれば扱えるんじゃね?
MPLで浮動小数使いたければfloatやdoubleをコンピュータが内部でやってるのと同じ事をMPLですればいい。 ただものすごく面倒臭いし遅い。 0xではコンパイルタイムにfloatとdouble使えるけどね^ε^
どこまで近似するか決めないと浮動小数演算そのものが無理だしな コンパイルが糞遅いのは、プリコンパイルヘッダが優秀なコンパイラならマシになる かもしれない でもまぁ現実的に考えればC++0x待ち
現行では整数の対で有理数を作って近似するしか無いね。 constexprの実装まだー。
あるクラスが ・メンバ変数Xをもっているか否か ・メンバ関数Yをもっているか否か を調べる方法はありますん? typedef Zを持っているかどうかはわかったんですが・・・
ちなみにやりたいことは operator []を持ってれば template <class T> void f(const T &val) { cout << val[0]; } operator []を持ってなくてfirstを持ってれば template <class T> void f(const T &val) { cout << val.first; } それ以外はコンパイルエラー といった感じで分岐させたいです
BOOST_MPL_HAS_XXX_TRAIT_DEFを使うとか?
>221 移植性のある方法では現行 C++ では出来ないと思う。 VC だと __if_exists があるし、処理系によっては SFINAE の適用範囲が広くて使えるかもしれない。 無理して頑張ったところでどうせ意味論までは確認できないんだから、素直に traits クラス作っちゃった方がいいんじゃないかな。
Boostライブラリはたまに移植性のない方法を無理矢理カバーしてるからなぁ あとC++0xなら普通に作るはず
TMPを発見するような事を真にハックするって言うんだよな
コンパイル時に文字列って操作できる? staticな配列が無いからタイプリストにchar2typeを詰め込んで・・・とか思ったけどすごいめんどくさそうだ
>>227 boost::mpl::string で?
もっと具体的にどういう操作がしたいんだ
文字列の基本的な操作ができないものかなと cpy,cat,cmp・・・などができて、実行時にはゼロ終端かstd::stringで取り出せる みたいな感じで
まぁ何だ、プリプロセッサも立派なメタプログラミングだぜ!
機能的制約はあっても制約を記述できない「ベーシックですか?」的なメタだけどな
>230 >228 の言うとおり boost::mpl::string でできるだろう。 ドキュメントのサンプルより: >typedef mpl::string<'hell','o wo','rld'> hello; >typedef mpl::push_back<hello, mpl::char_<'!'> >::type hello2; > >BOOST_ASSERT(0 == std::strcmp(mpl::c_str<hello2>::value, "hello world!"));
それ4文字以下のセットじゃないと使えないししかも環境依存しまくりじゃなかったっけ?
>234 multicharacter literal についてならその通り。4文字以下ってのも実装依存っぽいけど。 その辺は吸収するつもりなんだろ、きっと。primary test compilers だと test は全部通ってるみたい。 後、嫌だったら別に一文字づつ書いても構わないみたいだ。
TMPを理解するのに必要なIQはいくつですか? 126しか無いんですが、難しいですか?
しらねーけど子供の頃130だった俺は楽勝だから126でも大差ねーだろ
>>236 IQとTMPの理解にリニアな相関性はありません。
IQが多少低くてもセンスがあれば理解できるでしょう。
TMPが難しいのは修得人口が少ない(よって解説も少ない)のと C++のテンプレートが元々TMP用のものではないことによる不合理性が原因。 別に理論として難しいわけじゃない。
メタしないC++になんの価値が有るの いまどき
なんだと メタメタにしてやろうか小僧
C/C++のエラーチェックにこれまでGNU nanaを使ってきました。
boostにそういうものってありますか?
>>233 にある
BOOST_ASSERT
あたりがそれですか?
継承してる一番遠いサブクラスのサイズをコンパイル時に取得できる?
オンナスキーっていうレズキャラだせばよかったのに
template <class Gadget> class Widget { public: Widget(???) : m_gadget(???) {} private: Gadget m_gadget; }; m_gadgetをデフォルト以外で初期化したい、初期化パラメータはクライアントが選べるようにしたい でもWidgetはGadgetのことをよく知らないのでコンストラクタにどんな引数を持つべきかわからない これを解決したいんですが、Widgetの???をテンプレートパラメータから決定することはできますか?
c++0x なら Gadgetのコンストラクタ引数を可変引数 template にして: template <class Gadget, typename... Args> class Widget { public: Widget(Args... args): m_gadget(args...) {} private: Gadget m_gadget; };
template <class Gadget> class Widget { public: template <typename... Args> Widget(Args... args): m_gadget(args...) {} private: Gadget m_gadget; }; の方がいいか。
どうせなら perfect forwarding にしたいかもね。 別解として Boost In Place Factory とか。
ポリシーとトレイツのしっかりとした定義がわからない template <class T> class X : public T { using T::func; using T::num; int a[num]; }; ↑こういうのってtraitsなの?policyなの?
enable_ifか何かで定数の比較( > とか <= )で templateの特殊化分岐ってできましたっけ?
enable_if_cだった
そりゃできるだろ
眠かったので分けの分からん文章書いてしまいましたが、 250書いたすぐ後にenable_if_cで定数比較ができるのが分かりました。 <enable_if使ってできねーできねー言って悩んでたまぬけ
enable_ifでもMPLのint_とか適当に使えば行けるとは思うが、まぁenable_if_cで 済んでるのを無駄にややこしくする必要は無いな
struct Foo { template <typename F> Foo(F f) { typedef typename boost::mpl::if_c<boost::is_pointer<F>::value, function_ptr_tag, function_obj_tag>::type tag; // do something } } みたいに関数へのポインタか関数オブジェクトを渡す際、 関数オブジェクトのコピーを抑制するにはどうすれば良いんでしょうか? boost::ref 以外で。 関数オブジェクトの所有権を Foo 側で持ちたいので、最低 1 回のコピーだけで済ませたいのですが。 一応、試しに Foo (const F& f) としてみたら期待通りに動いたんですが、 boost::function とかはそういう実装になってないから、何か問題があるんだと思ったのですが。
ひょっとして今のテンプレメタってC++0x普及したらいらない子状態になるんですか?
なるわけがない
幾つかのテクニックはいらない子になるだろ
それは今のテンプレートメタが要らない子になるとは言わない
俺はLokiのInt2Typeを見て感動したなぁ。 整数定数を与えると、値ごとに異なる型を返すテンプレート。 99と逆な感じかな。
>>99 はコード上ではすっきりしてるけど、コンパイルすると普通に条件分岐やフラグ
を含んだコードを生成するよね
別にそれが悪いって訳ではないんだが
まあ、条件分岐やフラグをコンパイラに押し付けているのがポイントかね。 遠い将来にC++が自己書き換えプログラムを作るようになったら効率化するかもね。 誰か>202のマルチスレッドにコメントしてくれないかしらん。 boost::anyで標準対応してくれないかなぁ……
>>99 ってひとつのEXEであれば型の数が確定してると思うけど
最新のVCあたりなら最適化で定数になったりしないの?
呼び出される順序で値がかわってくるので完全にconstな関数やインスタンスからしか呼び出されてない場合でないと 定数に展開されない。
typeidのアドレスでも使えばいいんじゃないの?
というか正直
>>99 は使えそうで使えない罠コードにしか見えなくね
まあ、>99だと普通にマルチスレッドとか鬼門だと思う。 >266 type_infoに一意性てあったっけ?比較はOKだけど。
テンプレートのインスタンス化の度にインクリメントされる様な定数は無理ってこと?
静的な定数に最適化はされないんじゃね
静的じゃなくてコンパイル時定数と言いたかった
struct A { B operator (C); D operator (E); }; AとCorEをテンプレートパラメータにしてBorDを得るイディオムって有りますか?
C++0xなら decltype((*(A*)nullptr)(*(C*)nullptr)) Aがboostかtr1のresult_ofに対応していれば typename result_of<A(C)>::type どっちも駄目なら諦める
なんか3月にTMPの書籍出てたみたいだけど どう?買い?
どれよ
>>275 ISBN-10: 4798120391
(ISBN-13: 978-4798120393)
です
template好きはたぶん原書で読んでる ちょっと好きなだけの俺は邦訳を買ってみよう
原著たかくね?
内容考えれば安い。 これだけ高度な内容の方が出ている言語は珍しい。
隠し芸と言うか裏芸というか、こういう技覚えて皆実践してんの?
type erasureが必要だったから覚えた この程度に使うだけならそれほど難しいものでもないし
メンバでない関数 namespace x { r f(a1, a2, ...); } が存在するかどうか調べることってできる? リンクできるかどうかは流石に無理だろうから、宣言できるかどうかだけでも調べたい
int i; hoge h; fuga f; piyo p; for_each(i, h, f, p).do(print); とか int i, j; hoge *p, *q; for_each_pair({i, j}, {p, q}).do(swap); みたいな書き方を実現するテンプラテクニックってありますか? c++0xのみ可でもおkです
みたいなと言われてもその表記の意味する所がわからんのだが
>>285 異なる型からなるシーケンスにSTLライクにアルゴリズムを適用したいってこと?
後者は知らんが前者は
fusion::for_each(fusion::vector_tie(i, h, f, p), print);
とほぼ同意だからboost::fusionでも参考にすりゃ出来るんじゃないの
後者はそもそもi, i, p, qがboost::bariantoじゃないと無理だな
bariantoじゃなくてani-な
ruby厨か・・・
operator& がユーザーにオーバーロードされてても アドレスを取得できるようにするため
なるほど!
もちろん、原理を理解したら、普段はboost::adress_ofを使えばいい。
すまん、addressofだった
普通にアドレスとって欲しくないから&とかオーバーロードするのにキモイキャストまでしてアドレスとるなよって思う
COMやってたら CAdapt が必要になるようなケースで それが必要なくなるということか どっちもどっちな気もするが
ライブラリをジェネリックにしようとすれば 普段はしないような細かい配慮が必要になるってこった。
善し悪しはべつにしてなんでvolatileと引数のint longがなんのために存在するのかわからん
>>292 のコードで、なんでaddr_impl_refが必要なのかわからない
誰かおせーて
自然数の定数nを与えると、n≦m = 1<<x (n以上かつ最小の2のべき乗の値)を求めるテンプレートを組みたいのですが、 どのように組めばよいでしょうか? 例えば以下のコードのような感じで、n=33と与えると64を定数として求めたいのです size_t m = 1; while (m < n) m <<= 1; //事前展開してくれない
そういうのを見るとつい2の補数のアーキテクチャの時の面白ビット演算をやりたくなるが、 仮にアーキ依存していいとしたらテンプレートでああいうのって可能なんかな まぁどうでもいいが
>>304 ありがとうございます
再帰で書き直して置き換える感じなのだと理解しました
size_t binarywrap(size_t n, size_t m = 0) { return m < n ? binarywrap(n, m << 1) : m; }
boostが使えない環境なので以下のようにして使わせていただいてます
template <bool B, size_t T, size_t F> struct binarywrap_t { static const size_t size = T; };
template <size_t T, size_t F> struct binarywrap_t<false, T, F> { static const size_t size = F; };
template <size_t n, size_t m = 1> struct binarywrap {
static const size_t size = binarywrap_t<(m < n), binarywrap<n, (m << 1)>::size, m>::size;
};
template <size_t n> struct binarywrap<n, 0> { static const size_t size = 0; }; // これを省略するとなぜかエラーが出る…なぜだ…
基底クラスの数や型を得るメタ関ってできる?
308 :
デフォルトの名無しさん :2010/10/15(金) 23:05:36
こんなのを作ってみた。マクロ以外の呼び出せるもの 全部同じオブジェクトで呼び出せるクラス。 これもメタプログラミングなのかな? Delegate<Child*(int,int,int)> method[]= { &functor, //Child *operator(int,int,int);を定義しているオブジェクト &function, //Child *function(int,int,int); 普通の関数 Type(), //new Child(int,int,int);コンストラクター Typeは空のクラス Delegate<Child(int,int,int)>(&object,&Class::Method) //オブジェクトと関数のペア }; Delegate<Parent*(int,int,int)> parent_method=method[0]; //変換可能ならキャストできる 使い道としては関数ポインタの代わりとかイベントの伝達につかってるよ。 for(int i=0;i<n;++i)method[i](a,b,c);
>>308 boost::function に比べてなんかいいことある?
>>309 functionつかった事ないから知らんけど、
bindがあっても無くてもいい所と、コンストラクターになれる所くらい?
あとは、コードサイズが違うかもしれん。
>>310 それらはfunctionでもできるね。
>>309 プログラム技術習得として、function相当の機能を作った経験はあったほうがいいと思うぞ。
/** 移植性のないユニークな識別子 * 関数定義が増えたり#includeが増えたりすると値が変わる(セクション内の定義位置が変わるので) */ //@{ template<class T> inline unsigned UniqueID() { return reinterpret_cast<unsigned>(UniqueID<T>); } template<class T> inline unsigned UniqueID(const T&) { return UniqueID<T>(); } //@} template<class T, class U> inline bool InstanceOf(const U&) { return UniqueID<T>() == UniqueID<U>(); } template<class T, class U> inline bool InstanceOf(const T&, const U&) { return InstanceOf<T>( *reinterpret_cast<U*>(0) ); } template<class T, class U> inline bool StrictInstanceOf() { static_cast<T*>( reinterpret_cast<U*>(0) ); static_cast<U*>( reinterpret_cast<T*>(0) ); return true; // 相互に型変換が不可能ならここでコンパイルエラーで止まる } template<class T, class U> inline bool StrictInstanceOf(const U&) { return StrictInstanceOf<T, U>(); } template<class T, class U> inline bool StrictInstanceOf(const T&, const U&) { return StrictInstanceOf<T, U>(); }
メンバ関数ポインタを汎用的に格納するにはどうしたらいいんだ void*じゃダメなのはわかるんだけど
Boost.Anyのソースを読むといい。
>>313 遅延実行が目的ならstd::function、std::bindが一番頭使わない方法かな
stdになければtr1かboost
あるいは
>>308 のようにtype erasureやcompositionの技法で
自分で書くこともできるけど、スマポも格納したいとか、safe boolを
実装したいとか、いろいろ考え出すと結構面倒
このスレちっとも進まないですよね 所詮ねらー風情にはオーバーテクノロジーなんでしょうね
テンプレートより自家プリプロセッサの方がよくね
C++0xが普通に使えるようになったらメタ関数をいちいち typename HOGE<HUGA>::type ってしなくても HOGE<HUGA> で済むようになるから使用頻度は増えると思う。 現行のメタ関数はlazyな解決に使う方向だな。 template<typename MetaFunc> using Eval = typename MetaFunc::type; template<typename T> struct LazyIdentity { using type = T; }; template<typename T> using Identity = Eval<LazyIdentity<T>>;
319 :
デフォルトの名無しさん :2011/04/27(水) 11:52:39.52
このスレちっとも進まないですよね 所詮ねらー風情にはオーバーテクノロジーなんでしょうね
C++相談室で十分だから。
ぶっちゃけこの辺の技術を使うには、ぐぐって自力でどうにかする能力が必須
ちょっとTMP使うだけでも阿呆のようにコンパイル時間とオブジェクトサイズが増えるのは 早めに何とかしてもらいたいものだ。 コンパイラの人が頑張ればどうにかなるのかはわからないが。
スクリプトでヘッダとソース生成したほうが簡単柔軟コスト安だよねJK
そもそもその手法にはプリプロセッサマクロと同様の問題がある
いやぁ、どう考えてもLisp辺りで生成した方が柔軟で面倒が無いわ
どの辺に時間がかかっているんだろう
forthみたいなimmediateワード欲しいね。
>>327 素人考えだと組み合わせの生成と検索じゃね
TMPやってる人ってコンパイル時にかかるコスト計算とかもしてるの? これは展開にO(n^2)かかる〜とかこの処理はオーバーヘッドが大きい〜とか
時間がかかる程高度なことやってる気になる
>>330 Boost.MPL のアルゴリズムにも計算量が定義されていたりする。
333 :
デフォルトの名無しさん :2011/05/04(水) 14:40:18.86
テンプレートでプログラムを表現するコードを書いてみた。
http://codepad.org/Ol10cCgK 実行時にできる事をテンプレートで作成してもなんの意味も無いけど、
テンプレートプログラムを元にクラスを生成するならオートマトン(構文解析器等)
作成なんかで便利そうな気がする。
オートマトンでは構文解析はできんぞい
いや、できるな。ごめん字句解析の限界とスタックをオートマトンで構文解析する方法を混同してた。
もしかしたら拡張するかもなクラスに 余分に使わないテンプレート引数を設定するのって普通?
デフォルト引数ってそもそも、引数の変更が有っても MethodExExExみたいなのを書かないようにする仕組みじゃないのか?
>>336 後から追加できるのに、わざわざ先手打つ必要ないでしょ。
組み合わせ爆発起きそうなテンプレート群でもない限り。
>336 拡張した後に特殊化で互換性取った方が良くない?
クラス定義中に自分自身のサイズを知る方法はある? template <〜> class hoge { typedef hoge this_type; static unsigned int const this_type_size = ???; // this_typeのサイズを知りたい };
template<〜> class hoge{ enum{ size = sizeof(hoge) }; } hogeを直接クラス内で書けばテンプレート引数は省略できる。よってthis_typeは必要ない。 staticおよびconst修飾ではなくenumでとるべき。
>>341 enumを使う必要はない。
今時C++03未対応のコンパイラーなんて、
そもそもテンプレート自体ろくに扱えないだろうし。
class c{ int a[sizeof (c)+1]; }; サイズ取れたらどうなるの?
クラスはクラス定義の終了以後に定義されるので、
クラス定義内では、クラス名は不完全型として扱われる。
sizeofのオペランドに不完全型を渡すと鼻から悪魔。
そのため、
>>341 ,354のようなコードは不可。
クラス定義内のメンバー関数定義における仮引数と戻り値の型は、
クラス名を使ってもいいとされている。
そうしないと、クラス定義内で自分のクラス型を使うメンバー関数を定義できないから。
>>346 > sizeofのオペランドに不完全型を渡すと鼻から悪魔。
コンパイルエラーになるだけだよ。
C++ではそうだけど、sizeofに不完全型を渡すってのが鼻から悪魔の元ネタだからつい。
>>348 C++のほかにsizeofっていうとCぐらいしか思いつかないんだけど、
Cでも同じでコンパイルエラーになるだけだよ。
元ネタとか、何の話してんの?
「すべきでない」だとほとんど誤訳、誤読に近いね。 (適用する余地が少しはあるように読める) 規約の"shall not"は「してはならない」と訳す。 "shall"は「しなければならない。」 この辺の用語、訳は法令に準じてる。 原文でももちろん同じ。 上のURLの記事はどちらも酷いなw
>>350-351 いやshall notに違反したらundefined behaviorだってちゃんと書いてあるだろ
>>352 あれ?クラス宣言内でデフォルトの引数書けたっけ??
GCC拡張だったような記憶ががががが。。。orz
>>353 よくわからん。
> If a "shall" or "shall not" requirement that appears outside of a constraint is violated, the behavior is undefined.
というのはみつけたがsizeofの説明はconstraintsなんだから上記には該当しないで
> "shall not" is to be interpreted as a prohibition.
こっちじゃないか?それとも別の記述?
>>355 ここ。
5.1.1.3 Diagnostics
> A conforming implementation shall produce at least one diagnostic message (...) if
> ... or translation unit contains a violation of any syntax rule or constraint, ...
>>356 それは診断メッセージの話であって一連の流れとは無関係に思えるけど。
未定義動作の一つとして診断メッセージを出してエラーにするというのはありでも
違反があったときに診断メッセージを出さなければいけないからその違反は未定義動作であるということにはならないでしょう。
358 :
356 :2011/05/10(火) 02:04:23.78
>>357 ごめん。結論をちゃんと書いてなくて紛らわしかったね。
未定義動作にはならなくて、コンパイルエラーになるだけっていうほうの根拠を挙げたつもりだった。
> constraint > restriction, either syntactic or semantic, by which the exposition of language elements is to be interpreted なのでconstraint違反は、interpretされない=コンパイルされない=コンパイルエラーを出して終了、だろう。 だからsizeofに不完全型を渡すは未定義動作じゃなくコンパイルエラーだな。
TMPで整数型のビット幅を求める完璧な方法はある?
sizeof(T)*CHAR_BIT こういう話??
それは全然パーフェクトではないらしいです
任意の整数値とは書いてないからねー。
完璧かどうかはわからん #include <iostream> #include <limits> #include <type_traits> template<class T> struct Bits { enum { value = std::numeric_limits< typename std::make_unsigned<T>::type >::digits }; }; int main() { std::cout << Bits<int>::value << std::endl; std::cout << Bits<short>::value << std::endl; std::cout << Bits<char>::value << std::endl; return 0; }
template<class car,class cdr> struct Cell; typedef Cell<class X,Nil> cell; Cellが本体未定義でも使用可能なのと同じで、 Xは未定義でも、template引数に直にclass Xと書いてやれば、 XをCellに渡せる訳だけど、このXどこか広域空間以外の名前空間に 所属させる事できないの? Xの実体は不要で、templateを特殊化するための識別子としてだけ 使いたいんだけど、広域空間にあると他の名前との干渉が気になって 安易に使えない。
>>367 namespace CellTags { class X; } とでもしておけばいいんじゃない?
>>368 struct Example
{
typedef Cell<class X,Cell<class Y,Nil>> cell;
};
っていうほんと使い捨てな用途に使えないよ。
こんな感じで書くのと変わんないし。
struct Example
{
typedef Symbol<0> X;
typedef Symbol<1> Y;
typedef Cell<X,Cell<Y,Nil>> cell;
};
>>369 ふーん。
長いサフィックスをつけるマクロでも作れば?
なるほど。その手があるな。 もう少し代替手段を考えたいとこでもあるけど。
>367 Cellを含めて適切なnamespaceに置いたら?
>>372 実際には関数の中で使用するからどこの名前空間で使われるか解らん。
もっと現実に忠実に書くとこんな感じ。
Foo<Evalute< S< Setq,struct X,S<Quote,S<Lambda S<struct Args>, S<いろいろ処理> > > > > > processor(xxx,yyy,zzz);
それで使い捨てなのか
TMP こだわりすぎて 損をする 人に任せて 成果だけ得る
>>375 Tだすせ得
Tこ損人成
・・・どう読むんだ、
>373 無茶言うな。 せいぜいCRTP使って唯一性を確認するのが関の山だろ。 とりあえずVC++2010で動いた。鼻から悪魔かもしれんが。 int unique() { static int i(0); return i++; }; template<typename car> struct Cell { static int id() { static int i(unique()); return i; }; }; template<typename T> struct CellTagBase { template<int i> struct id; friend T; }; class Tag : public CellTagBase<Tag> {}; class Tag2 : public CellTagBase<Tag2> {}; // class Tag2 : public CellTagBase<Tag2> {}; --> error int main(int argc, _TCHAR* argv[]) { std::cout << Cell<Tag::id<0> >::id() << std::endl; std::cout << Cell<Tag2::id<1> >::id() << std::endl; std::cout << Cell<Tag::id<0> >::id() << std::endl; return 0; }
型消去でSTL仕様のアロケータの型を消そうかと思ったんだけど rebindできないことに気がついた。これって解決不能だよね? class hoge{ vector<fuga, type_erased_alloc> v; template <class A> hoge(A const &a) : v(a) {} }; みたいな感じで使いたいんだけどどうにかならないかな
>>378 型消去の意味が解らんけど
aをvに複製するのであればアロケーターを置き換えることは可能。
>>377 実行時の値はどうでもいいんだからそれ意味なくね。
>380 2回目のTag2の定義でエラーになるということがポイント。 こうすることで、この名前空間におけるTag2の唯一性を検証できる。 >378 type erasureは型情報をplaceholderの外には出せない……と思う。 使うときに明示的に変換するか、マルチディスパッチするメソッドを用意する(>202)しかないんじゃない? 単に格納するだけだったらboost::shared_ptr<boost::any>の方が簡単だと思う。
>>381 いや、話の流れからすると
>>373 の悩みは、struct Xやstruct Argsを
シンボル名代わりに使ってみたけど、あとからenum Argsとか定義する事になったら
struct Argsが衝突しちゃうじゃん、他の宣言と干渉しない手っ取り早い
シンボルって作れないの?って事だと思う。
型消去の意味が分からない人は型消去かtype erasureでぐぐっといた方がよさげ (この界隈限定で)割とメジャーな言葉だと思うし
>>383 1.delegateの仕組み
2.genericsのように入り口と出口だけ型を制限し、
Objectの中ではvoid*のような極端な抽象型を使う仕組み
どっちでも無いようにみえるけど具体的に何なん?
>384 2の逆。 placeholderの中では具体的な型情報を持っているけど、placeholderを管理するholderは 型情報を持たない抽象型を扱う。 boost::anyが実装例。 >382 型の特殊化を併用すれば名前の浪費は防げるね。
>>385 Delegate<Child(int,int,int)> method[]=
{
&functor, //Child operator(int,int,int);を定義しているオブジェクト
&function, //Child function(int,int,int); 普通の関数
Type(), //Child(int,int,int);コンストラクター Typeは空のクラス
Delegate<Child(int,int,int)>(&object,&Class::Method) //オブジェクトと関数のペア
};
だからこういうヤツでしょ。
この例だと内部でvirtual Child operator(int,int,int)を定義したオブジェクトで個々の型をラップしてある。
しかし、
>>378 が何をしたいのか解らん。まずtype_erased_allocが自作のクラスなのか
hogeの外で定義されたテンプレート引数なのか。そもそもアロケータの型を消すってのも
何を指してるのか解らんし。
>386 boost::any見ろって。 boost::anyにはどの型のオブジェクトでも保存できるけど、boost::anyには 保存している型の(静的な)情報が含まれない。 >386 はAdapterパターン?
>387 いや、こんなの。 template<int i> class Tag; template<> Tag<0> : public CellTagBase<Tag<0> > {}; // template<> Tag<0> : public CellTagBase<Tag<0> > {}; --> error
template <class T> struct type_erased_alloc { struct holder_ { virtual ~holder(){}; virtual void *allocate(size_t s) = 0; /*その他のメンバ*/ }; template <class A> holder : holder_ { typename A::template rebind<T>::other a; holder(A const & a) : a(a) {} void *allocate(size_t s) { a.allocate(s); } /*その他のメンバ*/ }; template <class U> struct rebind { typedef type_eraseed_alloc<U> other; }; holder_ *p; template <class A> Hoge(A const & a) : p(new holder<A>(a)) {} template <class U> Hoge(Hoge<U> const & other) ; // これが書けない }; こんな感じでrebindができなくなってしまう。やっぱ無理か コンパイル切るためにクラステンプレートからテンプレートコンストラクタにしたいんだが・・・
>>392 変な所が多すぎてどう問題をとらえていいか解らん。
1.Hogeってtype_erased_allocのコンストラクター?
2.type_erased_alloc自体にallocateが要るんじゃないの?
3.holder_ *pはどこで使われるの?
4.これが書けないっていうのは、関数の宣言の部分が書けないの?
それとも関数本体の内容の書き方がわからないの?
5.宣言の問題だとしたら、type_erased_allocのTがUで取れないって事?
6.どうでもいいけどtemplate<class A>のあとのclassが抜けてね?
>392 そりゃムリじゃね? テンプレートコンストラクタが受け取った型情報はあくまで関数内に閉じ込められたものだし。 Aの情報はholderに閉じ込められるからtype erasureとしての価値があるわけで、Hogeに残っていたら 意味ないだろ。まあ、ソースコードが良く判らんから何とも言えんが。
単にコピーコンストラクタを書きたいのなら、boost::anyのcloneあたりの実装を参考にするのが良いと思う。 あるいは型に依存した色々な処理を行いたいのなら、動的なマルチディスパッチしか無いですな。 そっちは>202参考 というか素直にvector<boost::shared_ptr<boost::any> > 使え。
396 :
デフォルトの名無しさん :2011/06/03(金) 20:44:02.27
>>392 コードが足りなすぎてよくわからんけど、holder_を外にだせばいいだけじゃないの?
あともう一つ、コピコンで受け取ったHoge<U>をさらにholderで包むこともできんじゃないの?
ともかく正確なコードを書いてもらわんと解らん。ただし別にallocatorの規格で決まってる部分は
書かなくていいよ。手を加えたとこだけ見せてくれ。
::type ↑ これウザくない? 結果が組み込み型とかになるならまだしもさ 継承とかできるならして::type書かなくていいようにすればいいじゃん なんでみんなこんなだるい書き方するの?
>>373 みたいに、最後で評価するようにすればいいだろ。
まぁ、それでも1回は必要になるだろうけど。
>>397 ちなみにそれは0xになっても型の遅延評価として残り続ける。
>>387 テンプレートエイリアスを使え
template < typename T > using add_ptr = typename std::add_pointer<T>::type ;
add_ptr<int> ptr ; // int *
今無いものを言われてもねぇ。 VC6,0の悲劇を繰り返す気かい。
そこでマクロですよ
これ ; デリミタっていうんだけどさ、これをつけなきゃエラーになるような そんな言語使ってる奴ってどうみてもゴミだと思うんだけど もしかして「;」これ打ち忘れてコンパイルエラー出すのが楽しいの? そうか、二度と話かけんなよ 結局ただのゴミだったんだな
数学板で猫が暴れているのと同じように、この天使というコテもそのポジションになりうるのだろうか。
こんなクソみたいな発言しているんじゃダメだろ。
猫もクソみたいな発言しかしないよ。
猫のクソみたいな発言しかしないよ。
409 :
デフォルトの名無しさん :2011/09/08(木) 16:50:30.76
下のプログラムは、MinGW (gcc4.5.2)では一応、正しい結果がでますが、VC++2008(SP1)では 次のコンパイルエラーが出ます。VC++2008の問題なのか、それともプログラムに問題ありなの か教えて下さい。お願いします。 error C2593: 'operator +' があいまいです。 'std::complex<double> operator +<double>(std::complex<double>,double)' の可能性があります。 または 'std::complex<double> std::operator +<double>(const std::complex<double> &,const double &)' [引数依存の照合を使用して検出しました] の可能性があります ↓
410 :
デフォルトの名無しさん :2011/09/08(木) 16:50:55.54
template <class T> struct double_trait { typedef T type; }; template<> struct double_trait<int> { typedef double type; }; template<> struct double_trait<float> { typedef double type; }; template <class T> std::complex<T> operator + (std::complex<T> z, typename double_trait<T>::type c) { return z+c; } int main() { using namespace std; complex<double> z(0,1); cout<< z+1 <<endl; ... }
411 :
デフォルトの名無しさん :2011/09/08(木) 18:20:40.43
型がdoubleのときにVC++2008付属のSTL(Dinkumware)の中で complex<double> operator+(complex<double>, double) に相当するものが既に定義されていて、テンプレートパラメータT=double のときに実質、2重に定義されてしまうんですかねぇ。 でも、gccのSTL(SGI)ではなぜエラーにならないんだろう? まあ、Z+1の代わりにz+1.0とすればいいだけの話なんですが。
VCのバグ
413 :
409 :2011/09/09(金) 15:04:05.19
普通の演算子オーバーロードにすると、gccもVC++も動きました。 complex<float> zのサイズが8でもz+1のサイズは16になっているのが 謎ですが、これは<complex>内でコンストラクタテンプレートが用いら れているからでしょうか? #include "stdafx.h" #include <complex> std::complex<double> operator + (std::complex<double> z, int c) { return z + (double)c; } int main() { using namespace std; complex<float> z(0,1); char c=1; cout<<sizeof(z)<<endl; cout<<sizeof(z+1)<<' '<<z+1<<endl; int i; cin>>i; return 0; } 結果 8 16 (1,1)
414 :
デフォルトの名無しさん :2011/09/09(金) 15:07:04.11
訂正:z+1→z+c
お前がcomplex<double>を返してるから
416 :
デフォルトの名無しさん :2011/09/09(金) 21:38:45.81
そうだが、その前にcomplex<float>からcomplex<double>に変換する コピーコンストラクタがないと、コンパイルエラーが出るはずなのに なんで出ないのか? と言うのが本当の質問の意味だが。
規格読んでるのかい? 0xdraft 26.4.3 template<> class complex<double> { public: typedef double value_type; constexpr complex(double re = 0.0, double im = 0.0); constexpr complex(const complex<float>&); explicit constexpr complex(const complex<long double>&);
418 :
デフォルトの名無しさん :2011/09/10(土) 08:40:12.02
ふーん、constexprは次世代C++に正式に導入さっるのか? また、複雑さを持ち込んでいるような。 そもそも、ちょっと前のgccやVC++2008に導入されてるのか?
ISO/IEC 14882:2003 26.2.3 template<> class complex<double> { public: typedef double value_type; complex(double re = 0.0, double im = 0.0); complex(const complex<float>&); explicit complex(const complex<long double>&); つーかもうTMP関係ないだろ 0xスレなり初心者スレなりにいけ
420 :
デフォルトの名無しさん :2011/09/10(土) 10:20:47.29
complex<double> と complex<float>は別のクラスだから 型変換するためにコピーコンストラクタが必要だと思った が、クラステンプレートを実体化した後なら普通のコピー コンストラクタでokということか。
用語は正しく理解し使え。 話題にしてるのはコピーコンストラクタでなく complex<float>からcomplex<double>への(暗黙の変換も可能な)変換コンストラクタ。 流れで通じてるからってそれに甘えるな。
変換コンストラクターと変わらないのに、 あえてコピーコンストラクターと特別な呼び方するのってなんでだろ。 コピコン未定義だと暗黙の代入されるけどあれはしょせんC互換のコピーだし コンストラクター書くときに、変換コンストラクターとコピコンの区別を意識した事がない。
423 :
デフォルトの名無しさん :2011/09/10(土) 11:45:21.23
>>421 うぜぇ。カス!重箱の隅つついた事しかいえんのか?
>>422 explicitを指定しないコンストラクターはすべて、変換コンストラクターである。
コピーコンストラクターも変換コンストラクター。
コピーコンストラクターを定義するのは、それが特別な定義を必要としているから。
例えば、ユーザー定義のコピーコンストラクターがあれば、暗黙のコピーコンストラクターは生成されないなど。
>>423 >>418 にも突っ込んどいたら。仕様に対する個人の感想なんかいらんわ、聞きたいことだけ聞け。カス!って
コピーコンストラクタと変換コンストラクタを区別してない人って多いのか? 自分でクラスを書くときには単に必要なメンバ関数の一つという意味で区別する意識はなくてもいいけど 他人と話すときははっきり区別しないと言いたいことが正しく伝わらないんじゃないか?
多いわけない。 コピーコンストラクタがなんであるか知らない奴なんて初級ちゃん。
428 :
デフォルトの名無しさん :2011/09/10(土) 15:29:52.94
やれやれ、ゴミ共がすぐ湧いてくる。
430 :
デフォルトの名無しさん :2011/09/10(土) 17:32:39.75
これで、このスレは、しばらく過疎化します。 しかし、何でこのスレというか、C++スレには「俺は何でも知ってるぞ!」 と自己主張すぎる奴が多いのかね。若気のいたりかw 規格書を読め? お前はパリサイ人か! こいつ、天狗になって職場とか 掲示板でも嫌われてるだろ。 VC++ラウンジにもそういう奴いるし。 C++の固有の決まりなんて知るか!だから、C++が嫌われるんだ。糞が
>>424 いや変換コンストラクターの一種であるコピコンが存在する事がおかしいとは言ってないよ。
わざわざ同じクラスに変換する変換コンストラクターを、わざわざなんでコピコンって呼ぶのってのが疑問なんで。
>>427 変換コンストラクタとコピーコンストラクタの違いって何?
「暗黙で生成される」と「クラスと同じ型を引数にとる」以外で。
explicit指定がなくて引数をとるやつが変換コンストラクタ 非テンプレートで第1引数が自分と同じ型で第2引数以降がないか省略可能なやつがコピーコンストラクタ コピーコンストラクタは変換コンストラクタの一種ってわけじゃなく別の概念
>>433 よくわからん。
int a;
string b;
Numeric n,m;
n = static_cast<Numeric>(a); //変換コンストラクタ
n = static_cast<Numeric>(b); //変換コンストラクタ
n = static_cast<Numeric>(m); //コピコン
n = Numeric(a); //変換コンストラクタ
n = Numeric(b); //変換コンストラクタ
n = Numeric(m); //コピコン
n = a; //変換コンストラクタ
n = b; //変換コンストラクタ
n = m; //コピコン
n = Numeric( "100", 8 ); // 通常コンストラクタ
435 :
デフォルトの名無しさん :2011/09/18(日) 15:34:34.38
何らかの型Tがあって、その型は組み込み型か組み込み型への変換演算子を持っていると期待出来る。 最終的には型をlong, unsigned long, doubleのいずれかに変換したい。 というときに、型Tを最も適当に変換出来る型を取得するにはどうしたらいいだろうか? template<typename T> struct ConvertResult { typedef ??? type; }; template<typename T> typename ConvertResult<T>::type convert(T t); struct X { operator int(); }; // intへ変換可能 long n = convert(X()); // longになって欲しい
>>435 まず「最も適当」を定義してもらう必要があるんじゃなかろうか。
438 :
デフォルトの名無しさん :2011/09/18(日) 21:41:25.13
>>433 別にどうでもいいやん。
Aクラスから全く別のクラスBに変換するのならあってもいいが。
しかし、そんな状況はクラス設計が終わっとる
ただ、単にintからlongに変えるだけで値は変わらんでしょ。
暗黙の型変換演算子か、コンストラクタテンプレートをもっただけでしょ。
やたらと新しい概念を持ち込む「禿ども」、そしてそれを有り難がってる
「日本の馬鹿達」がうざい。
>>435 ConvertResult::operator long();
ConvertResult::operator unsigned long();
ConvertResult::operator double();
ConvertResult::type使わずこういう使えばいいんじゃね。
魔法の呪文 #if __cplusplus >= 201103L を打ちまくって気分だけでもC++2011を味わえばいい #else の妥協部分にも妙案が出てくるかもしれんし
http://codepad.org/VbGFMpCW templateで与えられた構造体のサイズを最小にしたくて頑張ってるんだけど
上のコードのFoo0〜Foo5を自動で生成することはできないかな?
今は構造体ごとにスクリプトで生成してるんだけどC++だけでできるなら(マクロなしで)教えて欲しい
変数名がでたらめならできるんだけどtemplateパラメータの順番と変数名のマッピングが崩れないようにしようとすると詰まった
template<typename A,typename B,typename C>struct small{ template<typename E,typename F,typename G>struct asmb_t{E x0;F x1;G x2;}; template<typename E,typename F,bool G=sizeof(E)<=sizeof(F)>struct cmp_t{typedef E t;}; template<typename E,typename F>struct cmp_t<E,F,false>{typedef F t;}; typedef asmb_t<A,B,C> v0; typedef asmb_t<A,C,B> v1; typedef asmb_t<B,A,C> v2; typedef asmb_t<B,C,A> v3; typedef asmb_t<C,A,B> v4; typedef asmb_t<C,B,A> v5; typedef typename cmp_t<v0,typename cmp_t<v1,typename cmp_t<v2,typename cmp_t<v3,typename cmp_t<v4,v5>::t>::t>::t>::t>::t type; };
あ、ごめ要点全然外れてたw
カウンタを定数で回すforがほしいんだけど、TMPでできませんか? template<int i> struct func{ void operator()(){ //カウンタが定数なので配列の長さや他のtemplate引数に使える int a[i]; sprintf_s<i>(a, "%d", 12345); } }; static const int start = 0, end = 3; static_for<start, end, func>(); を {func<0> f; f();} {func<1> f; f();} {func<2> f; f();} に展開するようなイメージ。
本題と違うところにツッコミだけど、 sprintf_s は黙って結果を切り捨てたりしないぞ。
template <int i, int j, class F> class For { F f; public: For(F f) : f(f) { } void operator () (void) const { f(); For<i + 1, j, F> g(f); g(); } }; template <int i, class F> class For<i, i, F> { F f; public: For(F f) : f(f) { } void operator () (void) const { } }; class F { public: void operator () (void) const { std::cout << "Hello" << std::endl; } }; int main(void) { F f; For<0, 2, F> g(f); // [0, 2) g(); return 0; } こんなん?
449 :
446 :2011/11/14(月) 16:39:03.77
>>447 ランタイムエラーでしたっけ。
数値のテンプレート引数を渡すものがぱっと思い浮かばなかったのでこれにしました。
>>448 ありがとうございます。
なるほど、こういう再起を作ればいいのか。
慣れてしまえば単純なんだろうけど、どうしても再起が直感的にわからなくて。
カウンタ定数を関数に渡したいので、ちょっと改造させてもらいました。
450 :
446 :2011/11/14(月) 16:39:33.78
template <int i, int j, template<int> class F> class For{ F<i> f; public: void operator () (void) const { f(); For<i + 1, j, F> g; g(); } }; template <int i, template<int> class F> class For<i, i, F> { F<i> f; public: void operator () (void) const { } }; template<int i> class F{ public: void operator () (void) const { char a[i]; sprintf_s<i>(a, "%d", i); } }; int main(){ For<2, 5, F> g; //[2, 5) g(); return 0; }
451 :
446 :2011/11/14(月) 17:04:27.39
あとは関数オブジェクトじゃなくてラムダ関数が渡せれば最高なんだけど templateラムダ関数なんてないしなぁ…
452 :
デフォルトの名無しさん :2012/01/12(木) 00:51:25.53
struct なにかの名前_tag {}; なんて感じの使い方の共通パターンどこかにまとめられてないでしょうか boost.MPL?
コンパイル時のクラス識別子整数的な目的で コンパイル時ユニークIDが欲しいのだけど可能ですか?
このスレをよく読むといいよ
template<typename T> struct test{ typedef T t; }; template<typename T> void hoge(typename test<T>::t v){} template<typename T> void moge(decltype(T()) v){} hoge(0); moge(0); こういう関数の引数の型をなんとか自動的に特定する方法はありませんか?
for(int i = 0 ; i != 10 ; ++i) { a[i] = i ; } これを a[0] = 0 ; a[1] = 1 ; // ry a[8] = 8 ; a[9] = 9 ; に展開したいのだけど、どう書くと実現できますか?
460 :
456 :2012/02/15(水) 09:14:33.77
テンプレート引数の減少というのでしょうか。 template<typename T> void hoge(typename remove_const<T>::type &v){}
2つの型のテンプレートが同じか判別するクラスを作成しています。 template<typename T, typename U> struct template_is_same{ static const bool value = false; }; template< template<typename> class T, typename T0, template<typename> class U, typename U0 > struct template_is_same<T<T0>, U<U0>> : is_same<T<T0>, U<T0>>{}; //is_same<T, U>::valueは同じ型かどうかを表す 引数の数を増やせばある程度対応できると思ったのですが、、
typenameではなく、整数などの引数を取るテンプレートの場合、どう書けば良いですか? template< typename A0, template<A0> class T, A0 t0, template<A0> class U, A0 u0 > struct template_is_same<T<t0>, U<u0>> : lib3::is_same<T<t0>, U<t0>>{}; こう書くと、A0が推定できないと出ました。
template< typename A0, template<A0> class T, A0 t0, template<A0> class U, A0 u0 > --------------------- template< typename A0, template<class> class T, A0 t0, template<class> class U, A0 u0 >
template <int N> struct Factorial { enum { value = N * Factorial<N - 1>::value }; }; template <> struct Factorial<0> { enum { value = 1 }; };
自作のコンテナがSTLの要件を満たしているかどうか確かめるメタ関数ってないんですか!?
libstdc++にtestsuitsが付いてるから、 チョチョイと改変して使ってみたら?
467 :
デフォルトの名無しさん :2012/10/02(火) 20:48:07.55
std::vector<std::string>またはstd::list<std::string>を返すテンプレート関数を定義したい。 std::stringはそのまま使いたいので template<typename T> T <std::string> func(std::string s) { T<std::string> ret; ret.push_back(s); return ret; } とやったら t.cpp(3) : error C2988: unrecognizable template declaration/definition t.cpp(3) : error C2059: syntax error : '<' というエラー, さてどう書けばよいでしょう? std::vector<std::string>全部をテンプレート引数にして↓ template<typename T> T func(std::string s) { } や template<typename T> T func(typename T::value_type s) { } がOKなのは知っていますが、関数の引数,コンテナの値タイプはstd::stringに限定したい。
template<typename<typename> T> T<string> func(string);
function<R(T)>がT &&でなくTを引数にする理由は?
じゃなくてアルゴリズムがfunc(Iterator, Iterator, Pred)のようにPred &&でなくPredを引数にするのはなんで?
>>468 t.cpp(4) : error C2947: expecting '>' to terminate template-parameter-list, found '<'
t.cpp(4) : error C2988: unrecognizable template declaration/definition
t.cpp(4) : error C2059: syntax error : '>'
>>470 それはコピペ間違いだけど、本質的じゃないです。これでも同じ。
template<typename T> T<std::string> func(std::string &s)
{
T<std::string> ret;
ret.push_back(s);
return ret;
}
template <template <typename...> class T> T<std::string> func(std::string s)
>>473 おお、すげー
typename Container
じゃダメで
class Container
じゃなきゃダメらしい。classをtypenameで置き換えられないケースって初めて知った。
PS.
typoして気づいたけどVS2010は↓でも通りますね。(>>)
typename alloc = std::allocator<T>>
VC++のバグ
連続で書いちゃうとシフト演算子と誤認するバグだっけか
テンプレート構文後付けで追加したときに構文ルールを変更しなかった制限。 バグと言えばバグだけど。
479 :
デフォルトの名無しさん :2012/10/03(水) 18:06:14.97
構文の問題じゃねえぞ 字句解析の仕様の問題だ
構文ルールを変更しないと対応できないから残ってたんじゃん。
481 :
デフォルトの名無しさん :2012/10/03(水) 21:44:00.17
字句ルールと思ってればいいよ
寒い
>>482 2.12 Operators and punctuators
The lexical representation of C++ programs includes a number of preprocessing
tokens which are used in the syntax of the preprocessor or are converted into
tokens for operators and punctuattos'
preprocfessing-op-or-punc: one of
略 >> 略
だろ?
だから文法だけ直しても駄目なわけ。
字句ルールと思ってればいいよ
486 :
デフォルトの名無しさん :2012/10/05(金) 01:33:25.61
まあまあそういわず
(それが正しいんだから、)字句ルールと思ってればいいよ(。そうすべき。)
ネストした template-parameter-list を >> で終わらせられるような文法を書けばいいのでは〜
>476 にあるように、もう C++11 では字句ルールが修正された。
質問スレかどうか悩んだんですがメタプロな気がするのでこちらに書きます。 C++のテンプレートを使えば型や基本型の値を抽象化したクラス等が作れますが、 「変数名」を抽象化する方法ってありますか? 例) template<typename T> void func(T hoge){std::cout<<hoge<<std::endl;} の「hoge」という変数名まで抽象化できたらなーと思ったのですが。
マクロ(プリプロセッサ) そもそもすでに仮引数名そのものが呼び出し時に渡される実引数を抽象化したものになっているんだが
すでに抽象化された仮引数の何をさらに抽象化したいのやら
質問は具体的に。
最近C#始めて、C++との違いに戸惑っているのですが、 C++の変態的なTemplate Meta Programingから C#のGeneric? Meta Programingへの置き換えを 扱っているようなサイトはありませんんか?
そもそもTemplateとGenericは似て非なるものなので 置き換えようとすること自体無理があります
全部置換えられるとは思っていません。 出来ないなら出来ないと分れば良いです。
SFINAEが理解できん…
どのレベルでの理解できんだよ? テンプレートの基本を正しく理解できているなら SFINAEも基本は単純で特別なところは無いうえにあって当然のごく自然な処理だからたやすく理解できるぞ 応用になると話は変わるが基本を正しく理解できていれば一歩ずつ理解していけるだろ
SFINAEでできること全部、言語レベルでやって欲しい
オーバーロード テンプレートの特殊化 SFINAE どれも、○○に適合するかしないか、で振り分けか・・・
テンプレートメタプログラミングは最近勉強し始めたんですが これって機能の実装中に考えるものではなくて、 一通り実装し終えてから高速化するために考えるものって解釈でいいんでしょうか? 実装しながら考えるとマジで呪文書いてるみたいに思えてわけわかんなくなるんですが
オレオレライブラリを作ってみると良いよ アプリを作りながら覚えるようなものではないと思う
テンプレートメタプログラミングはプログラマブルマクロですか?
擬似関数言語と言われているようです。
constexprを使うとだいぶ楽になる 再帰は免れないけど
constexprだと最適化で再帰が平文化されて深度気にしなくていいって聞いたことあるんだけど本当?
んなわきゃない 再帰->ループの最適化が可能ならconstexprとは関係なくされるし ループに変換できないならコンパイル時計算であっても再帰で処理されるから限界はある
実行時に再帰の深さでスタックオーバーフローになることがない、という質問ならその通り。
C#のようにダイナミックなメタプログラミングも面白いと思うんだがC++じゃ難しいかな メタ属性の自動生成的なTMPテクニックは無いものか
そういうライブラリ書いて使えば。