Generic Programming with C++ Template
1 :
デフォルトの名無しさん :
01/12/17 21:45
じぇねりっく
3 :
デフォルトの名無しさん :01/12/17 23:22
とりあえずネタふり。 1で挙げた Modern… は、3章まで読んだ。いままでのところ、ムズいと 感じたのは 1章かな。ポリシーというのになじみがなかったもので。 正直、ポリシーと特性 (traits) の違いがよくわかっていない。 3章はテクニックの話なので、むしろ分かりやすかった。LISP という よりは prolog とかの単一化のイメージに近いね。こんなことが template でできるということには驚いたが。でも、タイプリスト なるものの使い方については、まだ、まったくわからん。
何ができるのか具体的に書いてくれよ。
一個のタイプミスで百行ぐらいエラーを出せる。
>>3 > でも、タイプリストなるものの使い方については、まだ、まったくわからん。
型によってコンパイル時に関数を選択させる場合に使える。STL で似たようなことをやってるのは、
iterator によってアルゴリズムを選択してるヤツかな。たとえば advance() は
randome access iterator なら iter += n
forward iterator なら ++iter を n 回
で処理するようになってる。(あれの魔法の種は iterator_traits なんで、ちょっと違うけど)
具体例: 1の本の「推薦の言葉」から。 // コンパイル時にチェックできる assert template<bool> struct CTAssert; template<> struct CTAssert<true> {}; で、たとえば CTAssert<sizeof(int) == 0> とかやるとコンパイルエラーを 出してくれる。ぜんぜん generic ってな感じはしないけどね。
STLスレでやれよ。
9 :
デフォルトの名無しさん :01/12/19 02:52
>>8 意味わかってる?
Generic Programingとは違う。
この本に載っている技法は「Generative Programming」生成的プログラミング
といわれるだぜ?
俺は「Generative Programming」萌えだ。
C++のtemplate特性を逆手に、とった巧妙な技法だ
ちなみにC++に依存してるわけじゃない。
たぶんPerlでもASPでもできる。
漏れも Modern ... 読んでる YO! 楽しい NE! デモチョトボクニハムズカシイヨ…
いったいどういうものなんですかね?>Generative Programming いわゆるGoFのPrototypeパターンとは別物? それともLISPのマクロみたいに実行時にクラスを 生成するのか?(C++では絶対無理だと思うが。。。) #例外が実装される前は良く使ったけどなぁ>C++
12 :
デフォルトの名無しさん :01/12/19 03:27
>>11 >それともLISPのマクロみたいに実行時にクラスを
>生成するのか?(C++では絶対無理だと思うが。。。)
もちろんLISPのようなクラスを生成というのは無理だ。
ある意味、LISPの様にC++でも生成できる様にしている。
templateを使いクラスを生成するためパーツを作ってるんだ。
なんか面白そうだなぁ。。。GoFの23パターンとは 違う新手のアーキテクチャーなんだろうか? 訳書で4800円か。。。まずは立ち読みから(;;
上のものは誤解を招きそうなので補足する。
(まあ俺は消防だから話半分ぐらいで聞いてくれ)
Generative Programmingとオブジェクト指向は直行している
Generative ProgrammingとSTLを使うとHaskell的プログラミングができそうだ。
「Modern C++ Design」のHP
ttp://cseng.aw.com/book/0,,0201704315,00.html にLokiといライブラリが公開されている。
見てみてはどうかな?
(サンプルコードが無いから本を読まないと使えんか)
>>11 Generative じゃなくて Generic の方だが、俺は次のように理解している。
手続き型のプログラミングでは「手続き」を定義することで、
オブジェクト指向プログラミングでは「インターフェース」を定義することで、
ソフトウェアの抽象化を進めた。
それでも抽象化できてないものの一つに「ループ」なんてのがある。たとえば整数の配列や
文字列をコピーするコードは、効率を考えなければどれも
for (i = 最初; i < 最後; ++i)
dst[i] = src[i];
みたいなものだが、これは手続き型でも OO でも、汎用的には書けないわけだ。コピーする
「手続き」、たとえば memcpy とかあるだろと反論するかもしれないが、あれは
特定の型やデータ構造に縛られる
という点で、汎用的ではない。たとえば C++ のオブジェクトなんかは、単純にメモリをコピー
して済ますわけには行かない。参照カウンタつきのクラスなんかは、そんなことしたら確実
に壊れるし。
そこで「一連の要件」を定義することで、汎用的で再利用可能なアルゴリズムを定義できる
ようにしたのが Generic プログラミング(C++ の規格書読んでると Assinable Type とか出
てくるけど、あれが要件)。ただ「一連の要件」というのが曲者で、手続きや型と比べると把
握しづらいんだよな。
C++ でうまくテンプレートを使ったコードを読むと「このループ何」みたいなことが少ない。
ループや比較に名前がついていて、コードを読んで意図が汲みやすいようになってる。
いまどき変数を使わずアドレス直書きなプログラムなんざ
「たとえ正しく動いていようが、こんなプログラムメンテナンスできん」
と思うように、将来は名前の無いループや比較演算を直接埋めたプログラムは
「読めるか、こんな抽象度の低いコード」
とか言われるのかも知れず。
直行ってなんですかー?
情報提供:三省堂 ■[直行]の大辞林第二版からの検索結果 ちょっこう ちよくかう 【直行】 (名)スル (1)途中どこにも寄らず、目的地へまっすぐ行くこと。「出張先から会社に―する」 (2)人の思惑などを考えず思うとおりに行うこと。「直言―」「―の士」 (3)正しいおこない。
18 :
デフォルトの名無しさん :01/12/19 04:30
>>16 まじれす
各概念が独立していること
単独でも使えるし、組み合わせることも可
(元ねた、XYグラフはX軸とY軸は直行している)
>>15 一種のTemplate methodと考えるのはまずいですかね?
>>18 一次結合のヴェクトルが一次独立なら「直交」が正しいと思う。
>>18 ちゃいます。
正直、ム・マ板では「直交」はNGワードですな(藁
>>19 正解(漢字が)
>>19 > 一種のTemplate methodと考えるのはまずいですかね?
それはあくまで「手法」の一つであって、背景にある「概念」とは異なると思う。オブジェクト指向って
関数ポインタですよね、というのと同じぐらいには外してると思うぞ。
(Generic プログラミングをサポートするのは C++ に限らないわけだし)
22 :
デフォルトの名無しさん :01/12/29 20:01
age
23 :
デフォルトの名無しさん :02/01/12 09:41
Builderつかってるんだけど、 テンプレート使ってると時々コンパイラがFatalErrorを吐く。 自分が間違っているのか、コンパイラの問題なのか分からなくて悩む。 ま、VC6よりはましだけど。 #とりあえずage
>>23 Templateだけ展開するコマンド無かったっけ?
25 :
デフォルトの名無しさん :02/01/13 15:50
>>23 どんなコードでFatalErrorになるの?
ちなみにBCC5.5はANSI C++には対応していません。
うそ書くなBorland
>>25 23 じゃないけど、たとえばこんなコード。
vector<vector<int> > vv;
for_each(vv.begin(), vv.end(), boost::bind(&vector<int>::resize, _1, 1));
致命的エラー F1004 vv.cpp 14: コンパイラ内部のエラー(関数 main() )
たしかね、 template <template class<> class C, typename T> C<T> function() {return C<T>();} みたいなの。 コードの方が間違ってる気もするんだけど…。 BCC5.5はISO C++と違う部分もいくつかあるけど (temlate <typename T> friend function<T>();がだめなのは参ったけど) まあ比較的頑張ってるんじゃないかな。 Windows用コンパイラでもっといいのある?
>>27 Modern C++ Design の著者は、サンプルコードを
Comeau C++ 4.2.38
CodeWarrier Pro 6.0
で動作確認した、と書いてある。あとは gcc 3.x 系列じゃないかな。
(妥協して VC7 ってのも現実的な選択肢だと思うけど)
>28 Loki の readme.txt に > Also, Loki has been ported to gcc 2.95.3 by Nick Thurn. ってあるよ.
30 :
デフォルトの名無しさん :02/01/13 19:01
generic programmingというのは、 objectを中心とするような王道OOとは違って、 generic functionを基本とするprogrammingのことね。 C++だと、template、operator/method/function overloadを使う。
31 :
デフォルトの名無しさん :02/01/14 00:49
Modern C++ Designは、CUJのExpert ForumとかGotWとか好んで見てる人に とっては必読の1冊ですよね。意外に早く翻訳されたのでよかった。 スマートポインタとかFactoryの話が出たので、ProxyとかFlyweightの例も 欲しかった気がしますが。 メインの開発環境がVisual C++ 6なんですが、Loki全部は通らないみたい。 Windows環境でコンパイル通そうと思ったら、CodeWarriorのWin版か Cygwin+α的なのに頼ることになりそうですかね? Lokiのうち、templateのパラメータにtemplate使ってるやつとか、 部分的な特殊化の入ってる部分以外は通ると思ったんで、そいつらを使わない 書きかたで置きかえられるかな、とおもってチャレンジしてみたんですけど 全て敗北しました。「あぁ、こりゃしかたないか」みたいに感じたんですけど、 単に、実力が足りんような気もするし。 部分的に汎用性を捨てて、固定のポリシーで書きなおしてやれば、 それはそれで、それなりに使えるような気もします。 Lokiを使いたいところだけ、通せるコンパイラでライブラリ化してやって そいつをVC6で使うのはどうだろうかと思ったんですが、それはそれで ライブラリの名前マングリングの話があって面倒なのでは、とか。 (試してみた人いません?) いや、、単なる感想で特に言いたいこともないんですが。。。
32 :
デフォルトの名無しさん :02/01/14 10:16
templateだとexportできないとライブラリ化できないと思う...。
う、、コンパイル不可なものは所詮をexportするわけにはいかん、と そういう指摘でしょうか。lokiをコンパイル可能なコンパイラに templateインスタンスをexportする機能がついているのか、という お話でしょうか。。 VC++なDLLの場合、templateインスタンスなクラスはexportできるみたいで。 ライブラリ側でポリシーの選択までやっちゃって必要なインスタンスクラスだけ exportする、という使い方はどうかと。export側とimport側でコンパイラとか 標準ライブラリのバージョンが違って出来上がるバイナリが変わってしまったら コケるかもしれませんが。 lokiそのものをライブラリ化しよう、というわけではないので、PImplな部分を lokiで作ってやって、dll exportなインターフェイスをつけてやれば、よいか と思ったんですが、実行時のパフォーマンスは落ちそうですね。 ライブラリ化してる時点でありがたみ半減には違いないです。
32 の言っているのは、template の前に付ける export キーワードのこと でしょう。私は、これをサポートしているコンパイラ (というかリンカか?) って見たことないです。 でも、33 の言うようにテンプレートを個々にインスタンス化したものは、 DLL の意味で export 可能だろうとは思います。
あぁ、exportですか。 なんかで見た記憶があります。プログラミング言語C++第3版だったと思うけど。。 正直いって、どういうしくみになってるのか想像できなかったんですよ、あれは。 テンプレートパラメータが残ってるから。 翻訳単位が違うってことは、テンプレートパラメータが何になってもいいよ、 っていうオブジェクトがあって、それが外部から参照できます、ってこと ですよね。それってどういう風に実装できるんでしょう、リンカ的に。 なんかいろいろ制約がつきそうですが。 (厨房に解説してやろうというかたお待ちしております) コンパイル済みオブジェクトにgenericな動作がさせられるっていうのは なにやら凄そうですが。
勝手な想像ですが、すなおに考えると、export を見た時点ではコンパイラは たんに export があったということを覚えているだけ。リンク時に未定義な テンプレートインスタンスが発見されるので、そこで初めてインスタンス生成を 開始。つまりリンカの協力のもとに遅延コンパイルをするという感じかなぁ。
37 :
デフォルトの名無しさん :02/01/16 04:52
>>37 そのページのタイトル、「COM+ 2.0 Generics」...
39 :
デフォルトの名無しさん :02/01/23 18:43
>>27 typoがあるYO。
template <template <class> class C, typename T>
C<T> function()
{
return C<T>();
}
40 :
デフォルトの名無しさん :02/01/24 10:44
>>39 失礼。書き間違えちゃった。
でも、39のでもダメなんだよね...。これって規格上だめなのかな。
41 :
デフォルトの名無しさん :02/01/25 03:11
>>40 functio < C < T > >();
じゃだめ?
>>27 >(temlate <typename T> friend function<T>();がだめなのは参ったけど)
これは言語の設計上できないようにしているだけ。
friend classは限定的につかおうってこと
>>41 27 が書きたかったのは、
template<typename T> class Hoge {
frind T function<T>();
};
ということだと思うけど。これは規格上 OK です。つか、function の後の
<T> の有無で意味が変わる。g++ は標準規格に合ってるけど、VC++ なんかは
合っていませんね。
>>27 ,
>>39 うーん、メタテンプレートみたいのを使いたいということ?
これのテンプレート引数の C って、それ自身がテンプレートになってるような
書き方だけど。
でも、そもそもどうやったらテンプレートそのものを引数として渡せるのやら。
>>42 それは、あのあと確かめたらBCC5.5.1はgccと同じ(規格と同じ)でした。ごめん。
関連することでは、今ISOの規格書読みながらいろいろ試してるんだけど、
template <typename T>
class SampleClass
{
//...
};
の定義の中で、
template <typename T, typename U>
void TestFunction(const TestClass<T> &, const TestClass<U> &);
をfriendにするにはどうしたらいいんでしょう。
BCC5.5.1だとどうやってもエラーになってしまう。
(「宣言が間違ってる」みたいなエラーだから、単なるコーディングミスかも知れない)
あの時書きたかったのは、
template <typename T>
class Hoge {
template <typename U>
friend class Hoge<U>;
};
みたいなのなんです。
(今回も手元にソース持ってきてないので適当に書いてますが...。)
サポートされてない、ってエラーが出ちゃうんだよね。
Effective C++の付録のsmart pointer実装例では使っているので、
規格決定直前に変更になってなければ規格上OKだと思うんだけど。
>>43 template引数にtemplateを使うのは問題ないはずなんだけど...
ごめん。 class SampleClass じゃなくて、 class TestClass です。 コンパイラ通してから書かなきゃだめだね、こりゃ。
うたがってすまんかった。たしかにテンプレート引数としてテンプレートを 取ることはできるね。でも、その有効な使い道というのがよくイメージできないなあ。
>>46 そのクラスがつかうコンテナを選ぶとか?
cls<vector>
cls<list>
>>44 規格によれば、
template <typename T, typename U>
friend void TestFunction(const TestClass<T> &, const TestClass<U> &);
でよいみたいだけど。でも、クラステンプレートの引数と T がかぶっているのは
まずいかもしれませんね。
friend クラスのほうは、
template <typename T>
class Hoge {
template <typename U>
friend class Foo;
};
でよいみたい。(foo の後の <U> がいらない))
>>44 だと、どちらも Hoge に
なってるけど、それは単なる typo?
49 :
デフォルトの名無しさん :02/01/27 01:01
今読んでる。 普通のC++プログラミングを実数軸の話とすれば、 テンプレートを使った繰り返しや再帰は虚数軸の話だと思った。 抽象度が高すぎるたとえですまぬ。
>50 をぃをぃ,それだけじゃ何を読んでるのか分からん人も出て来るだろ. まぁ Modern C++ Design なんだろうなぁとは思うが.
ごめん、この本専用のスレだと思ってた。 Googleで"Modern C++ design"検索してたまたまこのスレにたどり着いたので。 Functor萌え。
53 :
デフォルトの名無しさん :02/02/13 06:07
//from "C++ Template as Partial Evaluation" template<int N> class Pow { public: static const int result = Pow<N-1>::result * N; }; class Pow<1> { public: static const int result = 1; }; //... const int a = Pow<5>::result; //...
Factorial じゃないのか??
Functorはやはり関手と訳すのでしょうか?
56 :
デフォルトの名無しさん :02/02/13 06:53
>>53 >template<int N> class Pow {
>public:
> static const int result = Pow<N-1>::result * N;
こういう場合はstruct Powにしましょう。
非公開メンバー&メソッド無いんですから。
でもGenerativeプログラムの基本やね
汎化と特化のいい関係。
>>54 そう。スマソ。階乗とべき乗のどっち書くかぼんやり迷ってたから混ざった……。
>>55 classを類とは訳してないからいいんじゃない?(w
Generic Programmingってさあ、 C/C++のマクロのパワーアップ版って言ったらダメかなぁ。 オブジェクト指向マクロとか。
>>59 ダメ。機能限定版でもあるから(w。
・マクロはトークンならなんでも置き換えてくれる(予約語さえ)けど、
templateは型か特定の型の定数しか置き換えてくれない。
・マクロはパラメタのないトークンを置き換えられるが、
関数テンプレートは関数しか置き換えられないし、
クラステンプレートを使うには型宣言のときにパラメタ指定が必要。
・マクロ展開の際に引数は文字列として結合ができる
templateは与えられた引数を文字列として加工する能力はない。
・マクロはプログラムのごく一部にだけ選択的に作用させることもできるが、
テンプレートはグローバルに影響を及ぼす。
・・・・・・だからマクロとテンプレートには似た性質
(コンパイル時までに処理される)もあるけど、
別のものと思ったほうがいい。
62 :
デフォルトの名無しさん :02/02/14 02:50
//from "Expression Template Technique" //(1) Exp<T> and BinOp<T1,T2> template<typename T> struct Exp { typedef ContType T; virtual ContType eval(int i) = 0; }; template<typename T1, typename T2> struct BinOp : public Exp<T1::ContType> { T1 a1; T2 a2; BinOp(T1 arg1, T2 arg2) :a1(arg1), a2(arg2), op(operation) {;} virtual ContType operation (ContType, ContType) = 0; ContType eval(int i) {return (operation(a1.eval(i), a2.eval(i)));} };
63 :
デフォルトの名無しさん :02/02/14 02:50
//from "Expression Template Technique" //(2) operators : AddOp<T1,T2> and operator "+" overloading template<typename T1, typename T2> struct AddOp : public BinOp<T1,T2> { ContType operation (ContType a1, ContType a2) {return (a1 + a2);} } template<typename T1, typename T2> AddOp<T1,T2> operator+ (T1 a1, T2 a2) {return (AddOp(a1, a2));}
64 :
デフォルトの名無しさん :02/02/14 02:51
//from "Expression Template Technique" //(3) Vector<T> template<typename T> struct Vect : public Exp<T> { typedef ContType T; //... T* cont; int n; Vector(int size) : n(size), cont(new T[size]) {;} ContType eval(int i) {return (cont[i])} operator= (Exp<ContType> exp) { for(int i=0; i<n; i++) {cont[i]=exp.eval(i);} } };
65 :
デフォルトの名無しさん :02/02/14 02:51
//from "Expression Template Technique" //(4) sample expression //... Vector<double> v1; Vector<double> v2; Vector<double> v3; Vector<double> v_res; //... v_res = v1 + v2 + v3;
66 :
デフォルトの名無しさん :02/02/14 02:56
//
>>63 訂正
//from "Expression Template Technique"
//(2) operators : AddOp<T1,T2> and operator "+" overloading
template<typename T1, typename T2>
struct AddOp : public BinOp<T1,T2>
{
AddOp(T1 a1, T2 a2)
: BinOp(a1, a2)
{;}
ContType operation (ContType a1, ContType a2)
{return (a1 + a2);}
};
template<typename T1, typename T2>
AddOp<T1,T2> operator+ (T1 a1, T2 a2)
{return (AddOp(a1, a2));}
//
>>54 こんどこそPowだと思う(弱気sage)
template<int N, int X>
class Pow
{
public:
static const int reult =
(N%2==1)?X:1)*(Pow<(N
>>1 )>::result)*(Pow<(N
>>1 )>::result);
};
template<int X>
class Pow<0, X>
{
public:
static const int result = 1;
};
//...
const int pow5_5 = Pow<5,5>::result;
//...
68 :
デフォルトの名無しさん :02/02/14 06:50
>>67 static使うのはまずくない?リンカは削除できるのか?
あとコンパイル時に計算するのにN%2をやるのはなんかけなげ。
コンパイル時間を短縮するための効率的な構造とかてできそうで
怖い。SchemeをコンパイルタイムにやるC++は異常。
69 :
デフォルトの名無しさん :02/02/14 07:43
>>67 いやいやちょっとまて。static const intが
コンパイル時評価であることは保証されているのか?
てか?文は実行時だろう。とするとこれは
数字を保持したstatic intオブジェクトを
実行時の静的オブジェクト初期化時に順に掛けていくという
クレイジーなプログラムになるんじゃないか?
70 :
デフォルトの名無しさん :02/02/14 15:59
>>67 static const int じゃなくて enum にすれ。
>>67 template<int I,int P>struct Pow{
enum{R = I * Pow<I,P-1>::R};
};
template<int I>struct Pow<I,0>{
enum{R = 1};
};
>>68 テンプレートから展開されるクラス定義の数を減らす効果があるっす。>N%2とPow<(N
>>1 )>
クラス内のstaticはクラス1つに1個の意味だからそんなに仮に領域が割り当てられていたとしても、
クラス定義を処理する以上には悩ましくはないかと。>static
>>69 プログラミング言語C++第3版 A.5によれば
constant expressionにconditional expression(?: && ||)は含まれるらしいすよ。
ということは評価時に定数になるならば立派に定数式っす。
で、定数式ならコンパイル時に計算され、constに領域は割り当てられない筈。
具体的には
N=5
ならば
5%2=1 5
>>1 =2
2%2=0 2
>>1 =1
1%2=1 1
>>1 =0
が順に計算できるから
クラス定義の参照関係
Pow<5,X>→Pow<2,X>→Pow<1,X>→Pow<0,X>
という順序に従ってクラス定義が
Pow<5,X>←Pow<2,X>←Pow<1,X>←Pow<0,X>
と展開されていくので
Pow<0,X>::result=1、
Pow<1,X>::result=X*(Pow<0>::result)*(Pow<0>::result)=X、
Pow<2,X>::result=1*(Pow<1>::result)*(Pow<1>::result)=X*X、
Pow<5,X>::result=X*(Pow<2>::result)*(Pow<2>::result)=X*X*X*X*X
の順で初期値が確定する。
//
>>67 を一般の引数用に改良、多分展開されるはず。
template<typename T, int N>
class Pow
{
public:
T operator() (T x)
{
T pw = Pow<(N
>>1 )>(x);
return (((N%2==1)?x:1)*pw*pw);
}
};
template<typename T>
class Pow<T,0>
{
public:
T operator() (T)
{return (1);}
};
//...
double pow5_5 = Pow<double,5>(5);
//...
>>75 お家にはC++コンパイラ置いてないの(しくり)。今、容量に余裕がなくって。
とはいえ、
類似のコードは昔論文を読んだときに
g++で試したので、書き損じが無ければ
>>74 も動作はする筈。
inline展開と定数伝播の程度・能力に関してはコンパイラによるけど。
78 :
デフォルトの名無しさん :02/02/15 08:11
>>72-74 staticは意味が大きすぎてリンカは削除できないと思う。
5乗の計算に20バイト使う可能性がある!
constもinlineも保証はないので結局残るのはenumだけなんじゃないか?と。
運が悪いと普通のpowになっちゃいますよ的な。
そうして74のintの部分特別化にenumを使えるかなとかなんとか考えると疲れた寝る。
>>78 「意味が大きい」って?
あと20バイトくらいを問題にするなら展開されたコードの方が全然大きいかもよ?(w
大体enumの初期値として処理できる定数式なら
constの初期値として処理できない筈がない。
思うに、展開されたクラスのstatic constについて誰かがアドレス取らない限り
リンカまでも行かないで領域はないと思われる。
ちなみに、
Pow<N,X>::resultは定数式として定数の初期化に使えるところが利点。
Pow<T,N>(x)はNに関しては、
コンパイラが一般の部分特化のアルゴリズムを備えていなくても
テンプレートと定数伝播、inline展開の常識的な実装を備えてさえいれば
確実に部分特化の意図が伝わるのが利点。
初期のcfrontでトランスレートしてた時代ならイザ知らず、
constもinlineもここで出てる例くらいならば、今の最適化技術では
可能不可能の問題でなくやるかやらないかの問題だから、
一般用途のまっとうなコンパイラでは十分できる範囲だと思う。
>>79 だから、とりあえず手元の処理系で試してみろって。
>>74 BCCでためしたで
ASM見たけど思惑道理なってるで
>>81 よって問題なし、と。
規格について一通り調べがついた後は、「思う」と書いてあーだこーだ議論するより
実際処理系での結果を出した方が話が早いっしょ。
>>81-82 どうもです。
今、ようやく試せる環境(研究室の自分の机)にたどり着きました(w。
もう話は終わってるみたいですが。
84 :
デフォルトの名無しさん :02/02/15 18:07
>>79 20バイトというより1バイトさえも使っては意味がないし
コードが展開されてはそもそもいけない。
コンパイル時評価になることが保証されてこその新しいPow。
Pow<N,X>::resultは、コンパイル時評価は保証されないし
計算ごとに生まれる多くのstatic intが削除されることが
保証されないので恐ろしくて使えない。
Pow<T,N>(x)は、やはりインラインが保証されない上、
インライン展開されてもコンパイル時評価になることが
保証されないので駄目。
いままで標準準拠のコードを書くためにがんばってきたのに
ここでenumを裏切るのはなぜか。
あとcfrontがどうとか言い出すのが好感度下げる。ワラ
>>84 いいたいことはわかるが、templateでやる以上、
pow( 2.0 , 3.5 )とかやりたいね。
>>84 完璧確実を求めるならちゃんとPartial Evaluationなり、
2-level Languageなり使うしかないんでは?
元々C++の機能の有り合わせで実現してるんだから。
とりあえず両者とも(仮に最適化されなくても)規格的には最低限動作することになっていて、
少なくとも普及している処理系の一つで意図どおり動作するコードではあるのは確か。
ちなみに実行時にtemplateの展開処理をする珍しいコンパイラでない限り
Pow<N,X>::resultはコンパイル時に定数になっていなければならない。
当然定数式の必要なところでは定数として利用できる。
このコードの本来の目的はそれ。
領域が割り当てられて残るかどうかは副次的なことに過ぎない。
仮に、アドレスを取ったりできるように領域が割り当てられたとしても、
定数伝播の最適化とはまた別の側面の話なので問題はない。
(せいぜいメモリ使用量が増えるだけ。実行速度に悪影響はない。
元々展開テクニックではメモリ使用量ではなくて実行速度に重点が置かれる。)
それに標準準拠って言うけどstatic const intではダメでenumに拘る理由も結局不明。
初期化がコンパイル時に実行できないかどうかは、初期化式の側の問題であって
初期化される変数・定数の側の問題ではない。
裏切るも何も、列挙しない単一の定数の宣言にenumを使うほうこそ
考え様によっては病的だと思うがどうか?
(領域がないことを保証させるための抜け道だということは知っているが、
病的なことに変わりはない。)
あと、
>>84 君の好感度などはこの際限りなくどうでもよいこと。
もう一つ言えば、
これは標準数学ライブラリのpowを置き換えることを意図したものではない。
Pow<N,X>::resultは定数式の必要なところ(固定長配列の長さとか)で
べき乗の計算を行うために必要なだけのもので、
Pow<T,N>(x)は整数Nを固定したべき乗演算が繰り返される場合に有効なコード。
そういう特殊な用途以外の一般の場合には標準的なライブラリのpow()を使えばよい。
さらに言えば、これはGenerativeなコードをC++の有り合わせで書く場合に利用できる
テクニックを紹介するためのサンプルかつ部品である。
powだけ計算して満足しているわけではない。
>>85 残念ながらx^nのnは整数でないと特化できない。
>85 @sin( 1.46 )とかを展開するような 独自プリプロセサを書けや。
88 :
デフォルトの名無しさん :02/02/16 02:51
>>87 そんなことせんでもsin(1460000) // =1.46*1000000とかして
1000000で割ればいいじゃん。
古典的手法
>sin(1460000) sinをテンプレートで実用的にかけると仰る?
90 :
デフォルトの名無しさん :02/02/16 09:08
>>86 >少なくとも普及している処理系の一つで意図どおり動作するコード
それが駄目だとあれほど。
コンパイル時評価が保証されないので
全くGenerativeではない。君は
賢いコンパイラは仮想呼び出しを実呼び出しに最適化できるので
templateはいらない、仮想関数で十分。
領域が割り当てられて残るかどうかは副次的なことに過ぎない。
せいぜいメモリ使用量が増えるだけ。実行速度に悪影響はない。
多態性にtemplateを使うのは病的。
と思っている。確かにこれは正しい。ワラ
ここでSTLが大好きな君が裏切るのはなぜか。
つまりさあ、87とかの話題ってfixed演算なわけだよね。 そういうことしたいならLISPでプリプロでも書いたほうが自由度高いし簡単。 (defconst var `(,(sin 1.46))) ;;;リストvarにsin(1.46)の結果を埋め込み。 C++もコンパイル時に関数を実行できる仕様だったら便利なのにね。
べつにLISPじゃなくてもいいんだけどね。perlやRubyとかでも。 関係ないけどVBでこういうことができないのは不思議。
>そんなことせんでもsin(1460000) // =1.46*1000000とかして >1000000で割ればいいじゃん。 まさか・・・
94 :
デフォルトの名無しさん :02/02/16 18:05
>>91 C++で実装される言語がなにやらほざいているな
95 :
デフォルトの名無しさん :02/02/16 20:57
STLいいんだけどさぁ、 コンパイルエラー等ででてくる、エラーをどうにかしてほしい。
96 :
デフォルトの名無しさん :02/02/16 21:21
>96 をぉ!それは便利そうだ!!!! と思ったら VC 用かよ・・・ 残念sage
>>90 もう、その話題は良いって。
使えると思うヤツは自分のコンパイラで試した上で使えば良いし、汎用性が
必要なプログラムを書いてる場合には、それなりの対処しろ。
99 :
デフォルトの名無しさん :02/02/17 09:15
>>99 言葉遊びは、技術系の板の外でな。
Generic Programming を Win32 API と組み合わせてプログラミングしたって
良いじゃない。
「入門C言語」とか銘打っておいて、なかみをみると いきなりWinMainからはじまったりすると激しく萎える。
>>101 そんな本があるのかーΣ(゚д゚lll)
禿げしくスレ違いだが書名キボンヌ
94は煽りのつもりだろうか
104 :
デフォルトの名無しさん :02/02/21 23:00
良スレage
105 :
デフォルトの名無しさん :02/02/22 03:19
>>100 話のすり替えは、技術系の板の外でな。
enumを置き換えられると思いこんだんだな。
>>105 言語の仕様上はこの場合でもenumはstatic const intに置き換えられるのでは?
置き換えられないというなら実例をキボンヌ
>>106 もう相手にしないで、放っておいてやるのが良いと思われ。
>>91 この例の意義はC++が既に持っている機能でこういうことが書けると言うところに意味がある。
(
・実用的なGenerativeアプリケーションの開発
・Generativeを正式にサポートする言語の研究開発への動機付け
)
他の言語に替えてよければ、それこそLISPもそうだが'CとかMetaMLとか色々ある。
それにこの例はGeneric ProgrammingとGenerative Programmingの近しい関係を端的に示している。
かくしてtemplateによってC++は2レベル(コンパイル時/実行時)言語になってしまっているいるわけだが、 元々そういう用途を意図して設計しているわけではないので、 この2レベルで激しく構文が違ってしまっているという問題はある。 例えば……: template引数にはクラス・オブジェクトはおろか整数定数しか渡せない。 書きなれた命令型ではなく関数型プログラミングのスタイルで書かなければならない。 コンパイル時関数を表現するのにtemplateクラスを定義するのはやっぱ無理がある。 というわけでプログラミング言語学的には今後の研究が待たれるところであるっす。
111 :
デフォルトの名無しさん :02/02/22 22:31
>プログラミング言語学的 ぷ
112 :
デフォルトの名無しさん :02/02/22 22:34
>111 ぷ
113 :
デフォルトの名無しさん :02/02/22 22:57
C++Builder6の案内が着たけど 3ユーザーとしては買いでしょうか?
114 :
デフォルトの名無しさん :02/02/22 23:02
>>110 煽りはともかくとして、昔のCでマクロレベルでどうにかする、
ってのと基本的に変わらないね。
処理系がえらく大きくなった割には対効果が低いのが気になる。
>>108 'Cってなんですか?
quote-C?
>>114 今回の Pow() あたりだと、
> 処理系がえらく大きくなった割には対効果が低い
のは確かだが、STL の関数オブジェクトやアルゴリズムまで行くと、そう
捨てたものじゃないぞ。
templateあたりはもうちょっと洗練して縮小とかしてくれないと あんまり使う気になれないんですが。オブジェクト指向とか以前に。 LISPのマクロなんかは最小限の労力で物凄い効果を期待できますけど、 あんな感じになって欲しいな。
現状のC++って複数の言語使ってる感じなんだよね・・・
118 :
デフォルトの名無しさん :02/02/22 23:32
みんなC++なんて止めてほかの言語を使おう(笑
119 :
デフォルトの名無しさん :02/02/22 23:32
C#ですかあ?
120 :
デフォルトの名無しさん :02/02/22 23:34
AllegroCLでも使いますか?(笑
実行時型やtemplateあたりの登場からC++では「おや?」と 思うようになったな。 javaもgenericを搭載するらしいが、はたしてどうなることやら。 なんつーか、ポリシーを持って作ってほしいね。
122 :
デフォルトの名無しさん :02/02/22 23:40
C++ではなくObjectiveCが普及すべきであった、せめて。
Objective-Cが普及しないのは名前長いから? コミュニティが弱小だから? ともかくObjective-CをC++という名前にして、 今までのC++は無かったことにするとか。 ストラウストラップは始めからいなかった事に(w BorlandもDelphiと統合できなくて困ってるみたいだし。
124 :
デフォルトの名無しさん :02/02/22 23:52
MacOSXもC++で開発できるようには出来なかったらしい。 OSの設計に言語の汚さがついて行けなったらしく。 ObjectiveCがメインで、Javaでもなんとかなるとかならないとか。 C#登場で一気に滅亡しそうな予感もしてるんだな。
>>117 それは言えてる。
手続き、OO、汎用プログラミングなんでもアリなのはメリットだとは思うが、各々の
親和性がもうちょっと上がると嬉しい気がする。template がらみのエラーメッセー
ジとか。
C#はガベコレあるから、もはや別の次元でしょう。>124
127 :
デフォルトの名無しさん :02/02/23 02:27
最初の方で generative generative って言ってた人もう来ないのかな? generic なアプローチと generative な方法との違いが知りたいんだけど。
>>127 俺は最初の方の人とは違うけど、
generic
型に依存しない操作
generative
コンパイル時にポリシーを与えて、コードを動的に生成する
ってイメージがあるな。STL だと algorithm は generic だけど、container なんか
は generative っぽい気がする。
129 :
デフォルトの名無しさん :02/02/23 21:13
>>106 置き換えられないことを説明するのに疲れたよ
>>84 あたり読んでくれ
>>107 自分で言うのがまさに再起的でこのスレにぴったりだな。思われ君よ。
>>129 > 置き換えられないことを説明するのに疲れたよ
もう説明しなくていいって。書くことは一通り書いたんだから、後は読んだやつが
各自で判断すればいいだろ?
131 :
デフォルトの名無しさん :02/02/23 21:31
>>131 構って欲しければ、馴れ合い系の板に逝けよ(w
133 :
デフォルトの名無しさん :02/02/23 21:35
134 :
デフォルトの名無しさん :02/02/23 21:43
scheme読んでて思ったんだが (自分はgenerativeプログラミングは staticプログラミングとでも呼んだ方がいいと思う) factorialとかsumとかpowとか書いてると これらをさらにgeneralizeして マクロにする。Modern..本のTYPELISTみたく。 こんなことやってるライブラリはないんだろうかね。 intのリストは全部staticに処理できるのではないかと。 あまり役には立たないだろうけれども。
>>135 だから、放っておいてあげなよ。アレで本人は満足なんだから。
VC.NETのtemplateはまじでどうなったのかな。 たのむよ!
>>128 genericな関数の定義を効率よく実装する方法の一つが
パラメータ毎に展開してコード生成すること。
templateを利用したgenerativeテクニックはそのコード生成機能を逆手に取って
実現されている。
ちなみにJavaに導入されるtemplateは実行時に処理されるらしいので、
ここで話題になったようなコード生成テクニックには利用できない。
まぁ、Javaの場合、
コード生成素直にダイナミック・ロードでなんとかしろってことなんでしょうか?
140 :
デフォルトの名無しさん :02/03/03 00:22
保守age
141 :
デフォルトの名無しさん :02/03/03 22:31
Modern C++ Design買ったはいいけどまだぜんぜん読んでない。
>141 嫁
143 :
デフォルトの名無しさん :02/03/12 04:36
久しぶりにあげてみる
144 :
デフォルトの名無しさん :02/03/12 04:49
Modern C++ Design amazon注文age
スレタイが際立ってるな。
146 :
デフォルトの名無しさん :02/03/12 19:07
age
>>146 ageてばかりだと、そのうち
ageばっかりになるぞ
なんかしゃべれ
(ΦωΦ)フフフ・・・
(Φ∀Φ)フフフ・・・
150 :
デフォルトの名無しさんk :02/03/18 23:39
買ってきた。明日の朝9時までに3章までは毒派する予定。
この本、期待してたほどにはカルチャーショック受けなかった。 なんつーか、何かにつけてめんどくさいね。
153 :
デフォルトの名無しさんk :02/03/19 00:05
これに書かれてる内容のようなことはMLやHaskellだったら もっとスマートに出来るの?
154 :
デフォルトの名無しさん :02/03/19 03:20
>>151 haskellはともかく、MLはこういうことに関してはすんごいよ
156 :
デフォルトの名無しさん :02/03/19 05:49
>>154 HaskellやMLで出来ない技が多いよ。
たしかに、この本の中に出てくるFunctorは
関数型言語では高階関数(カリー化)というものと、とても似ています。
しかしC++のテンプレートは、ソースを実際にマクロのように展開しています。
こういうマクロのように展開することを関数型言語ではα簡約といっているらしいですが。
こういう機能はLispとSchemaにはありますが、MLやHaskellでは無いです。
本質を見極めた上で書きましょう。
157 :
デフォルトの名無しさん :02/03/19 11:32
マクロ展開できることは本質的なことなんですか?
158 :
デフォルトの名無しさん :02/03/19 16:08
159 :
デフォルトの名無しさん :02/03/19 16:33
正直、Cのマクロを多少強化すれば解決する問題が多い気がするんだけど
>>159 「多少強化」がやろうとすると多少の強化では済まないことも多いからなぁ。
タイプ・チェックも計算能力も。
Lispに追いつこうと頑張るのは凄いけど、 > > >と最後の閉じカッコがなんともまぬけでイイ(w
<<157 何時、評価&簡約されるかということ。 α変換(C++で言えばプリプロセッサによるマクロの展開、テンプレートの展開)はコンパイルされるとき展開、簡約されますね。 β変換(実行時に引数を渡すこと)は、実行時に評価、簡約されます。 何時評価されるかって結構だよね。 訂正:α簡約なんていう言葉は無いです。α変換の間違いです。 漏れも逝きます。
# α簡約と言わないことも無いと思う。。。
164 :
デフォルトの名無しさん :02/03/20 17:14
165 :
デフォルトの名無しさん :02/03/20 21:49
>> 【Generative and Component-based Software Engineering】 かなり抽象度高くて眠くなる。 C++ で Lisp ごっこをやる章は楽しかったけど。 学術的な雰囲気の強い本なので、そういう素養がないとつらいとおもう。 (OOPSLA の論文読んで理解できるレベルなら十分。)
167 :
デフォルトの名無しさん :02/03/21 01:11
age
168 :
デフォルトの名無しさん :02/03/21 01:17
これからlokiみたいなライブラリが増産されていくのかと思うと、 楽しみと思う反面、地獄の予感もしたりする、、
169 :
デフォルトの名無しさん :02/03/21 01:46
だれか、
>>53 みたいなやつで、LOG書いてくれ。
170 :
デフォルトの名無しさん :02/03/21 02:20
>>162-163 β変換がβ簡約とも言われるのは適用されるたびにλ項が解消されて減っていくから。
(ある種のλ式ではβ変換を有限回適用することで簡約順序に関わらずそれ以上簡約できない
「標準形」になることがわかっている。無限回簡約できるようなλ式、
またその中でも評価順序によっては有限回でそれ以上簡約できなくなるようなλ式もある。)
α変換は名前の付け替え変換だから式の形自身は変わらないので、
無限回繰り返すこともできるが、
同一視することによって無視する(α合同関係)ことが多い。
というわけで、α簡約とはやっぱりあまり言わないかも。
まー、マクロ展開にせよテンプレートの展開にせよ
単純なλ計算そのものではない。
例えば、プリプロセサマクロの名前付け替えは、
付け替え後の名前が付け替え対象の名前になるような関係による
循環を避ければ有限回で終了する。
それでも敢えて喩えて言えば、
プリプロセッサのマクロ展開だからα変換とも限らず、
引数つきマクロなどはβ変換といってもいいかもしれない。
肝心なことを書き忘れた。
>>170 つまり標準形のあるλ式(計算が終了する)であるならば、
λ項はβ変換適用ごとに減っていくので「簡約」なわけです。
通常、計算は終了することに意味があるとされるので、逆に
β変換が「簡約」であるようなλ式を「正しい」プログラムの表現
と見るわけです。
ついでに言えば、現実のプログラムでは評価順序も決まってるから、
その評価順序において簡約し切れるような式であれば良いわけで、
標準形のあるλ式以外にも、特定の簡約順序によって
有限回で簡約不能な式(値)になるような式も
条件付で認めるが立場あり、実はプログラムの基礎理論としては主流です。
172 :
デフォルトの名無しさん :02/03/21 04:24
>>171 =170
わかったから。
そいうことは関数型言語板かLispShcema板でやって
お願い
>>172 ModernC++Design読むと逆にSchemeとかMLやってみたくならねぇ?
これから10年後のC++のプログラムとか、今のクラスライブラリの
惨状から想像するとぞっとするんだけど。
>>172 この本のやってることってtemplateでどこまでconst演算できるか?
ってのもあるからあながち無駄でもないかも。
>>173 もちろん無駄だといってる訳ではない。
ModernC++Designを読んでる最中にHaskellに出会って
今、はまりまくってるよ。
そのせいか、STLもパラメータ化クラス(型?)を使いまくってる性で
関数言語風味たっぷりに感じてるよ。
どれくらい嵌ってるかというと、関数プログラミングからホーアCSP理論まで読んで
「ほー、Eiffelの表明の元ネタは仕様記述言語Zから来てたのは知ってるけど
そのZ言語の元ネタはCSP理論なんかー。おもしれーなー。
表明の推論もできそうだなー」とか訳のわからんことを考えるくらい嵌ってる。
ただ、この手のネタは、この板の主旨から結構ズレてしまったのでは?
と思うわけよ。
>>174 これも面白いと思う。
非正格言語でtemplateみたいなコンパイル時簡約?みたいなことが
出来たら実行速度が手続き型言語に勝てる関数型言語も夢では無いかもしれない
と俺は創造してしまう。
(CleanやMLは代入使って実行速度を上げてるようだが、そんなセコイことせずにな)
でも、なーtemplateは形検査してくれないからなー。
ModernC++Designの技はやり過ぎだと思う。
ハッタリには使えると漏れも思う。
(研究する価値が無いというつもりは無い。そこは酌んでほしい)
>>172 やっぱり実践的なプログラムにあれは使うものじゃないよね。
Cの変なテクニックを積み重ねたようなプログラムなんて物凄く
読みにくいけど、それの上を逝ってるよ。
あれは「上には上がいるもんだが、ここまでやっちゃあいかん」という見本だ。 頭の体操には悪くないが。
COBOLでオブジェクト指向、みたいな話になってる気がする
まぁでも実際に使ってみないことにはなんとも言えないね。
180 :
デフォルトの名無しさん :02/03/22 00:00
テンプレートの特殊化に対する適合アルゴリズムについて詳しく解説してる サイト、キボーン!(懐)
181 :
デフォルトの名無しさん :02/03/22 14:42
gcc3.0でLOKIは動きますか?
182 :
デフォルトの名無しさん :02/03/22 23:17
>>181 動くらしい。(LokiのReadMeに書いてなかったけ?)
Lokiがコンパイルできる珍しい処理系
183 :
デフォルトの名無しさん :02/03/23 03:59
VCじゃできないのか??
184 :
デフォルトの名無しさん :02/03/23 04:41
BCCでもだめなのにVCで動くかー
185 :
デフォルトの名無しさん :02/03/23 08:19
>>183 じゃ、駄目じゃん、、、
いったいなんでgccでは動くのか、その理由が知りたいな。
実際、ここまで互換性がないとテンプレート怖くて使えないんだけど。
>>185 あるSTLの本の第一章に。
「互換性が低いことを怖がってSTLに対して保守的にならないで下さい。
時代はstanderd C++に向かっているのです。」
>>185 VC++ だと部分特殊化もメンバ関数テンプレートもサポートしてないから…
つーかもう4年近く前のコンパイラだよ?<VC6
VC.NETだとどの程度templateに対応してるんだろ。
VC.NETでLokiコンパイルしてみたひといる?
一応MSDN MagazineにはBoostやLokiがちゃんとコンパイルできる、 って書いてあったが<VC.NET
191 :
デフォルトの名無しさん :02/03/23 14:18
>>185 gccが開発バージョン2.9から最新ANSI C++規格を実装したからさ
それと.NETでLokiは使いたくないなー。VC.NETはやめとけ。
氏ぬぞ。
gccマンセー
Lokiってどこにあるの?? サイトがでかすぎて分からないヨ
194 :
デフォルトの名無しさん :02/03/23 14:47
195 :
デフォルトの名無しさん :02/03/23 14:49
サンクス〜〜♪
Loki初めてみた。 凄ぇ・・・まさに天才。
197 :
デフォルトの名無しさん :02/03/23 15:19
みんなあれを最後まで理解した? おれは3章であっぷあっぷだよ。 あんまりテンプレート自体を使いこなして内省かも。
色々とお褒めの言葉をならべてもLokiを使ったサンプルコードが 出てこないところをみると皆自分の中で消化吸収してる最中なのかな? おれはあと3ヶ月ぐらいはかかるだろうな。
199 :
デフォルトの名無しさん :02/03/24 01:38
あげ!
Lokiすごいけどさ、やっぱりすごいだけで泥臭いと思うよ。
201 :
デフォルトの名無しさん :02/03/24 01:58
つーかおれはそもそもテンプレートの構文が嫌いだ。
202 :
デフォルトの名無しさん :02/03/24 15:19
こらこらtemplateあってのC++だ。
203 :
デフォルトの名無しさん :02/03/24 17:12
漏れもそうだ。 C++使う理由の大半はテンプレートがあることだからね。 STL なーんて素晴らしい。
じゃ、templateのないC++はなんなんだyo!
非互換C
206 :
デフォルトの名無しさん :02/03/24 18:26
207 :
デフォルトの名無しさん :02/03/24 18:43
あんな糞言語と一緒にするなよ
やばい。ちんこ勃ってきた。
209 :
デフォルトの名無しさん :02/03/24 18:58
210 :
デフォルトの名無しさん :02/03/25 06:47
C#にはテンプレートに該当する物はあるのか?
つーかeval相当はないの?
212 :
デフォルトの名無しさん :02/03/25 09:09
213 :
デフォルトの名無しさん :02/03/25 09:58
Ruby以外の言語は使い物になりません。以上。
214 :
デフォルトの名無しさん :02/03/25 11:11
えっへん!
216 :
デフォルトの名無しさん :02/03/25 12:52
あの本の一章に書いてあるポリシーパターンだけでも 結構使えるよな。テンプレートパラメータからホストクラスを 派生させるってのカッコいいから使ってるよ。
217 :
デフォルトの名無しさん :02/03/25 12:56
Int2TypeとかType2Typeもね
VS.NETを購入された方へ質問があるのですが、C#にはC++でいうところの STLに該当する機能はあるのでしょうか。購入検討の資料としたいのです。
>>218 よく知らないけど、System.Collectionsのコンテナを
使うんじゃないかな?だからSTLは無いと思うけど。
220 :
デフォルトの名無しさん :02/03/25 14:39
タイプリストはなんか凄そうなんだけどあれをどう活用するのか 分からない。だれか簡単に説明してくれないかな?
221 :
デフォルトの名無しさん :02/03/25 20:04
222 :
デフォルトの名無しさん :02/03/26 00:06
223 :
デフォルトの名無しさんk :02/03/26 00:37
今タイプリストの使い方を色々と本読みながら考えてるんですが、 class Cls { public: //このクラスにおいて関係するタイプのリストを作成する //(全てのアプリケーションコードにあるクラス内において必須) typedef TYPELIST_3(Cls1, Cls2, Cls3) MyClsList; ・・・ private: //必要なインスタンスを作成する Loki::TL::TypeAt<MYClsList, 0> cls1; Loki::TL::TypeAt<MYClsList, 2> cls3; }; とかって感じにタイプリストからの型選択テンプレートクラスに リストを渡して選ばせる感じに使うんでしょうか? なんか頭が固くていい使い方が思い浮かばないなw クラス間の関係が明確になるメリットは大きいかな。
224 :
デフォルトの名無しさん :02/03/26 01:04
アプリケーションコードにおいてもテンプレートパラメータの 諸関係だけを記述するようなプログラムを作るのってかなり頭痛いよね。 上の奴もCls自体をいくつかのテンプレートパラメータ(タイプリスト)を もらうように直したら、かなり自由度は上がるけどもう何がなんだか 分からんものになりそうな・・・ アプリケーションプログラマにそこまで要求するんか!の世界。 この本読んで任意の処理に対するタイプリストの設計を勉強しないと 全然ダメだな。 こういうのはもっと若いうちにやりたかったよ。。。(遠い目 Lispハカーは、こういったやり方でいつもプログラミングしてるんですか?
225 :
デフォルトの名無しさん :02/03/26 01:28
>>223 その設計は良くないのでは?
(タイプリストの引数の数が変わったとき作りなおさなやね)
今手元に本が無いので上手く掛けないけど・・・
TypeListのクラスを単一継承するという活用法が載ってた
と思うけど、そってで攻めてみては?
あっ。Cls2,Cls3,Cls4見たいにしたらいいんか
226 :
223=224 :02/03/26 01:36
>>225 今まではOO的なプログラミングということでインターフェイスを
規定してそれに対して実装するってやり方だったけど、これは
全然違うね。
最初にタイプリストありき。それの関係を記述するようなプログラミング。
あたま痛くなってくる。でもこれがホントの再利用性なのかも。
ダメだ、、、 馬ファ輪飲んで今日はもう寝る
>>223 =224
個人的にはType2Typeぐらいしか使いたくないなー
実際の開発に使えそうなものって何かな?
結論 天才が書いたコードは天才しか再利用できない
>>228 んー、自分でも色々と考えてるんだけど、これをつかった効果を
なんとなく想像するので精一杯。
イメージとしては、既存の開発において
ライブラリコード:アプリケーションコード=1:10
ぐらいの比率だったとして、Alexandrescu方式のプログラミングを
導入したことで
ライブラリコード:アプリケーションコード=8:2
みたいなところまで比率に上げる。というか外部のライブラリやシステムに
依存したものを極力排除する。そうして全体のステップ数を減らす。
こんな世界(w)を期待してるのは分かるんだけど、
いかにライブラリコードを設計するかは一筋には逝かないね。
システムの全体を理解してパターンを適用し、それらの関係を
リストで表現する。こんな天才的能力がある人だけが使うものかもね。
リストをデータ構造としか考えてこなかった俺みたいなヘタレには
そもそも無関係かも(w
STLで上がった生産性がアプリケーション全体に適応されたら
天才とヘタレの能率の差なんて目も当てられないだろな。
>>229 天才の書いたコードは天才しか再利用できないかもしれないけど、
ModernC++Designで言われているのは「自分の書いたコードぐらい
再利用しようぜ」ってことだと思う。
天才がこういったプログラム設計をあっという間に理解して
抽象度の高いプログラミングをしてると思うとカナーリ鬱なんだけど、
ヘタレもお遊び程度にはやっておかないと。
今日はショックで眠れないYO、トホホ
232 :
デフォルトの名無しさん :02/03/26 22:32
Haskellマンセー!!!
233 :
デフォルトの名無しさん :02/03/26 22:40
>>223 =224
クラス同士の機能が独立したものになるように
設計すればいいかも。
そのクラス同士を組み合わせるところにGenerativ Programming
を使えばよいと考えている。
しかし完全に機能が独立したクラスまで上手く機能を分割できないと・・・・
俺にはむりっす
おみゃーら、Haskellやれ。 C++のきったねー構文に関する知識は後から詰め込めばよし。 まずはプログラミングが何なのかを学ぶためにHaskellをやれ。
237 :
デフォルトの名無しさん :02/03/26 23:32
>>234 HaskellはIOとのやり取りが弱いので実用的ではない。
まあ、これは言語ではなく処理系の問題だが。
あとHaskellはマクロが無いね。
コンパイル時でないと知りえない情報(__FILE__とか__LINE__)が
かけない。すこし残念。
238 :
デフォルトの名無しさん :02/03/27 00:56
ああいったプログラミングテクニックってどこに書いてあるの? C++Report?DDJ?
239 :
デフォルトの名無しさん :02/03/27 01:07
単にLoki::SingletonHolderを使ってみるだけでも苦労した。鬱だ…
Loliは凄いけどタイプリストのマクロ定義にがっかりした人も多いはず! もっと柔軟なものをここでなんとしてでも作りませう!
241 :
デフォルトの名無しさんk :02/03/27 02:37
無理
242 :
デフォルトの名無しさん :02/03/27 02:54
俺には無理
静的型付け言語としてあれが精一杯だと思うけどどうだろ。 マクロの部分ならなんとかなるかもしれないけど。
(´・ω・`)ショボーン
>>242 Andrei Alexandrescu にも無理(だった)
>>240 どうでもいいが Loli じゃなくて Loki な。
246 :
デフォルトの名無しさん :02/03/27 14:22
Lokiは標準に準拠したコンパイラなら通らなければいけないコードなんですか?
247 :
デフォルトの名無しさん :02/03/27 14:23
C++がRubyにまさっている天安か有る?
249 :
デフォルトの名無しさん :02/03/27 14:30
やたああああああああああああああああああああああああああああああああ Ruby >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> C++
250 :
デフォルトの名無しさん :02/03/27 14:37
Ruby!!!!!!!!!!!
無いと > なのか? = って可能性は無いわけ?
252 :
デフォルトの名無しさん :02/03/27 20:45
ロリ>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Loki
>>251 たぶん operator>>>>>>>>...() だから stream から入力してるんだと思うが。
頼むからレス付けないでくれ。 別スレが丁度あるじゃん。
>>253 いや、激しくビットシフトしてるんだと思うぞ。
シフトしてる数は少ないけど、ビットシフトの勢いは激しいのかも。 はしっこのビットがはみ出すくらいに・・・
STLはインライン展開しまくってくれるのがどうも。。。。 確かに画期的だとは思うのだけど。 インラインしてくれる分、それだけコードは早くなるんだけどね。
>>257 コンパイラのオプションをいじって、最適化を「速度優先」から「サイズ優先」
に変更しましょう。インライン展開が、かなりの程度まで抑制されます。
259 :
デフォルトの名無しさん :02/03/28 00:33
260 :
デフォルトの名無しさん :02/03/28 00:33
>>257 最近のCPUではインラインしすぎはかえって遅くなることが
あるんで、よろしく。STLに限った話じゃないけども。
262 :
デフォルトの名無しさん :02/03/28 00:50
STL
WTLで、メッセージハンドラがマクロ内に インライン展開されてたのにはびっくりした。
>>263 そりゃマクロだからインライン展開するわな。
つうかマクロをインライン展開というのかは微妙
# あれにびっくりしたのには同意。
class Hoge : public CWindowImpl<Hoge>{ BEGIN_MSG_HANDLER(Hoge) MESSAGE_HANDLER( WM_HOGE ,OnHoge ) //OnHogeがここにinline展開される MESSAGE_HANDLER( WM_HOGE2 ,OnHoge2 ) //OnHoge2はここにinline展開される END_MSG_HANDLER() LRESULT OnHoge(){...} //ここではbpかけられない LRESULT OnHoge2(){...} };
>>265 そんなあなたに
__asm { int 3 }
(っつー話じゃないか)
267 :
デフォルトの名無しさん :02/03/28 16:36
Alexandrescuってさなんかデザパタの著者とかEffectiveやExceptionalの 著者に遠慮して本書いてないか?modern~はとても実践的な本だけど、もっとTypelistに 特化した馬鹿みたいなオタク本を書いて欲しいところだな。
268 :
デフォルトの名無しさん :02/03/28 23:13
もっと色んな実例を集めて紹介してほしかったりする。>Alexandrescu 彼のWebページは何だかな。
269 :
デフォルトの名無しさん :02/03/28 23:16
>>268 いやWebで公開するには惜しいアイディアがあるんだろ。
more modernが出るのをひたすら待つのみ
んなもん読む暇あったらChristopher Alexanderの著作嫁 Alexandrescuは彼のパクリ
271 :
デフォルトの名無しさん :02/03/28 23:20
>>270 知ったかしてます?
なんか具体的なこと語ってみてよ
272 :
デフォルトの名無しさん :02/03/28 23:24
Alexandrescuのテクニックはパターンの実装においても 使えるけど、それ以外のことにも可能性がある点が面白いわけで 270のような奴はそもそも勘違いしてるんだろな。
273 :
デフォルトの名無しさん :02/03/29 01:10
Functorのサンプルコード、g++3.0で動いた人いますか? なんかローダーがエラー返してくる。。
274 :
デフォルトの名無しさん :02/03/29 02:54
ああ、すまそ。SmallObj.cppをコンパイルするの忘れてた。失礼!
275 :
デフォルトの名無しさん :02/03/29 17:01
276 :
デフォルトの名無しさん :02/04/02 00:20
テンプレートあげ!
277 :
デフォルトの名無しさん :02/04/02 00:29
VCのtemplateの限界がわからん。 何処まで許されているのだ?
278 :
デフォルトの名無しさん :02/04/02 00:32
VCなんて捨て捨て。 これからはC++コンパイラといえばG++を指します。
279 :
デフォルトの名無しさん :02/04/02 00:35
G++って何ですか? VC、BCB、gccしか知らないものですから・・・。
gccのC++コンパイラがg++。
>>280 しかし g++ と G++ は、かなり違う気がするが。(特に UNIX だと)
g++はいいんだけど、autoconf,automakeの使い方覚えるのが 偉い大変だよな。みんなあれをすんなり覚えられた?
283 :
仕様書無しさん :02/04/02 01:35
CppTestつかいながら覚えるとよい。
最近のg++は、単にC++用のオプションをつけてgccを呼び出すスクリプトです。
285 :
デフォルトの名無しさん :02/04/02 17:43
あげ
スクリプトじゃなくてバイナリの実行ファイルになってるけど
$ man g++ G++(1) GNU Tools G++(1) 名称 g++ - GNU プロジェクト C++ コンパイラ (v2.4) 書式 g++ [option | filename ]... 解説 C コンパイラおよび C++ コンパイラは統合されました。 g++ は gcc に C++ を解釈するようにするオプションをつけてコール す るスクリプトです。詳細は英語版のオンラインマニュアルおよび gcc(1) を参照して下さい。
>>289 情報が古いと思われ。っつーか基本的にスレ違いだよな、この話題。
291 :
デフォルトの名無しさん :02/04/06 10:40
でも現実的に今、Lokiが使えるC++コンパイラといえば gccかCodeWarriorぐらい。 しかたがないね。 CodeWarriorかおか?
292 :
デフォルトの名無しさん :02/04/13 11:01
ついでにこっちもあげ
293 :
デフォルトの名無しさん :02/04/16 11:53
VC6でBCCで使える様にLokiを修正できないの?
そんな糞は捨て捨て gcc使いなさい。
糞クソ言わないでヨ! (`ε’)プンプン
296 :
デフォルトの名無しさん :02/04/16 18:04
>>293 できん。
特にVCでは不可能。
BCCでも機能が足りん。
テンプレートクラスの中でテンプレートクラスが宣言できない。
T1 < T2 < T3, T4 >, T5 >みたいな複雑なテンプレートの特殊化ができない。
これじゃねー。
面白さと革新さは認めるけどVCで使えないんじゃ はっきり言ってただのオナニーコードじゃん GCCだけで閉じられてる商用プロジェクトなんてあんまり ないんじゃないかと思うがどうよ? 結局現時点では実践向きじゃないって事?
299 :
デフォルトの名無しさん :02/04/16 19:07
>特にVCでは不可能。 >BCCでも機能が足りん。 これってテンプレートの限界を表わしてるよね。 これじゃ実用にならない。
300 :
デフォルトの名無しさん :02/04/16 19:50
300get!
>>298 テンプレートパラメータとしてタイプリストを
作りそのリスト値から任意の型を取り出せる。
>>299 vs7のコンパイラならいけるらしい。
それにlokiはansic++準拠だよ
テンプレートの限界じゃなくて
コンパイラメーカーの限界
理解できない→「んなもん、実用にならんわい」といいたくなる罠。 と、マンネリな煽りはさておいてvcも7.1で対応させるとか、させないとか。
>GCCだけで閉じられてる商用プロジェクトなんてあんまり うふ♪
303 :
デフォルトの名無しさん :02/04/16 20:12
p.210で、 素のC++だと、"Deriverd" という文字列からDeriverd型のオブジェクトを作成できなくて 云々とあるけど、この本のどのへんのコードを見れば文字列からオブジェクト生成するのが楽に 汎用的にできるのかがさっぱりわかんない俺はガス管くわえて死んだ方が世の中の為ですか?
>>303 コンパイラの内部表現としての型と
コードに記された型名の違いということではなくて?
305 :
デフォルトの名無しさん :02/04/16 20:32
name mangling の話…? は余り関係ないように思われ
>>298 本を読んでから、返事をください。
先の例より複雑なテンプレートがいっぱい出てきます。
>>303 本の例とは逆に
template < class T > class GetClassNameAble{
char* getClassname() { return T; }
}
みたいなことができても面白いと思われ。
>>306 そんなのいみねー
文字列からクラスを生成(Reflection)できると便利だが(構造上&仕様上不可能なのは承知)
>>306 の例だとほとんど使う意味がない
>>306 > 本を読んでから、返事をください。
> 先の例より複雑なテンプレートがいっぱい出てきます。
了解しますた。もっと勉強します。
>>299 「実用」の定義によるな。gcc で仕事してる人間には実用レベルだし、Win32
アプリケーションを VC6 で書いてる人間には使い物にならん。
ただ、VC も BCC もいずれ ANSI C++ 準拠してくるだろうから、そのときに
使える選択肢が一つ増えるって事で。
(そういや Boost に Loki 入れようという話、どうなってる?)
SHをターゲットとしたプログラムにタイプリストが使われまくり、 Windows上のプログラムでは未だに従来のデザパタのサンプルコード みたいなのが使われてるなんて、、、なんか違和感あるなw
>>306 クラス名を文字列化するのは typeid(T).name() で出来るし。別に面白くもなんとも。
で…どんなかんじ? 神。
313 :
296=306 :02/04/16 21:16
>>311 この例、面白くなーい?
残念だなー。
>>307 const char*なら、いけるんじゃない?
もしくはコンパイラが自動的にFactoryを作ってくれるというのも
面白いかも。
というかTypeListで作れるか。あはははは。
314 :
デフォルトの名無しさん :02/04/16 21:27
>>309 >(そういや Boost に Loki 入れようという話、どうなってる?)
って初耳なんだけど、本当なの?
誰か情報キボンヌ
ちょっと考えてみましたけども、sizeof(クラス)と、 そのクラスのコンストラクタのアドレスがわかれば、 実行時にダイナミックにクラスの作成できるかな? 実装依存(コンパイラ依存)なら書けるでしょうか?
317 :
デフォルトの名無しさん :02/04/16 23:32
LLが入りそうってのはどっかで見聞きしたなぁ。
318 :
デフォルトの名無しさん :02/04/16 23:49
>>315 Boost の開発者 ML で議論してる。スレッド長いから追ってないけど
Andrei Alexandrescu も話に参加してる模様。
(メールアドレスが @hotmail.com だけど)
>>316 実装依存って言ったらそれこそなんでもありやん
>>319 そそ、ダイナミックにソース作って、コンパイラ起動して、できたプログ
ラムに制御渡しゃどんなクラスでもできるぞ。
>>318 boost-dev(?) の ML 読んでんの?すげー。
所詮俺は厨房である事を再確認した・・・
cppmlぐらいなら分かるんだけどさすがにそんなところ
まで手は伸ばせんわ・・・
独り言sage
322 :
デフォルトの名無しさん :02/04/17 01:13
>>321 > boost-dev(?) の ML 読んでんの?すげー。
全部は追ってないし、開発にも参加してない。必要そうなヤツだけ斜め読み
だよ。(C++ は仕事道具だし)
Boost -- Boost mailing list
http://lists.boost.org/mailman/listinfo.cgi/boost > cppmlぐらいなら分かるんだけどさすがにそんなところ
cppml ではなくて cppll かしらん?
俺は cppll は最初は読んでたんだが、エピスが検定試験云々言い始めた頃に
S/N 比が許容値を下回ったので切った。最近はどうなん?>読んでる人
>>322 cppIIは今も取ってるが未読が1253通(藁
全然読んでないよ。
エピス氏はコード出して技術的な話をしているうちはいいが、
取り巻きも含めて雑談モードに入るとうるさいからな。
重鎮扱いで誰もつっこめないし。
>>323 俺も彼の言語感覚についていけないクチだね…
自動で s/ぢ/じ/g してから読めば少しはマシになるかな(w
うむ。 10代、せめて20代前半ならまだ許せるが、 某本で素顔の写真見ちゃったからなぁ・・・
あの写真はショックだったという人 わりといますね。典型的な(略)
だれかvcppかcppIIでエピス当てにうざいってレス付けてくれないか。 漏れは怖くてできない 電柱○家 Tit○w あ○る あたりが突っ込んできそうだな。 「いきなり出てきてあんたの方が役に立ってない」とかいいながら。
すとーるまんみたいな感じ?
全然。
330 :
デフォルトの名無しさん :02/04/17 15:39
331 :
デフォルトの名無しさん :02/04/17 15:45
332 :
デフォルトの名無しさん :02/04/17 15:48
C++でリフレクションが使えるようになる(前)処理系
333 :
デフォルトの名無しさん :02/04/17 21:10
>>322 あのMLでは「低いS/Nの中からいかに情報を取り出すか」というのも重要なテーマです(藁
うまいフィルタ作れないかな。もちろんcppで。
334 :
デフォルトの名無しさん :02/04/17 21:45
C++ Builderってバージョンあがってもう少し使えるようになるかと思ったら テンプレート周辺にバグがあるんでしょ?がっかり。 しっかりしてくれよ、Borland。期待してるんだから。Pascal以外の言語もがんばってくれよ。
>>334 えっ?初耳。ソースはどこかにありますか?教えて下さい
>>333 struct pr : public std::binary_function< string, string, bool>{
bool operator()(const string& x, const string& y)const{
return search(x.begin(), x.end(), y.begin(), y.end()) != x.end();
}
};
vector<string> articles;
・・・
articles.erase(remove_if(articles.begin(), articles.end(), bind2nd(pr(), "ぢ")), articles.end());
articles.erase(remove_if(articles.begin(), articles.end(), bind2nd(pr(), "ちう")), articles.end());
いっそのこと、 articles.erase(remove_if(articles.begin(), articles.end(), bind2nd(pr(), "FUKUDA Fumiki")), articles.end()); で。
339 :
デフォルトの名無しさん :02/04/21 22:28
>338-339 つまんねーよきみら
341 :
デフォルトの名無しさん :02/04/22 00:15
342 :
デフォルトの名無しさん :02/04/22 01:04
VC7へぼい・・ template<class T> void swap(T& x, T& y) {} template<class T> void swap(vector<T>& x, vector<T>& y) {} これコンパイル通らないんだよね・・ プログラミング言語C++ではこういう書き方してるのに。
>>342 using namespace std; を外して、std::vector にしてごらん。
344 :
デフォルトの名無しさん :02/04/22 15:47
あげげ
おまえらに質問。 最近関数オブジェクトがおもしろくてしょうがないんだけど、 引数がいっぱいあるメンバ関数をもつクラス T があるとして、 std::vector<T> t(100); std::for_each(t.begin(), t.end(), &T:func); みたいなのを引数渡ししつつぐるぐるやる方法はないかな。 mem_funcだとうまく引数が渡せないので、引数をなんとかする 関数オブジェクトをいっこつくってぐるぐるするしかないと思うんだけど、 いざコードを書こうとするとかっこわるくていかんのです。
どっちかというとSTLスレで聞くべきだった。 sage鬱
>>345 boost::bindとboost::mem_funとかで出来るんじゃないか?
>>347 たとえば引数が三つあるメンバ関数を考えたとき、
すべての引数に値を渡せるかな?
>>348 3つのうち2つが固定なら出来るんじゃないか?
351 :
デフォルトの名無しさん :02/04/22 23:34
>>343 template<T> void swap(T& x, T& y) {}
template<T> void swap(Class<T>& x, Class<T>& y) {}
2個のオーバーロード関数があいまいで最適な変換ができません。
STLソースではこうなってる模様
template<class T> Class {
public:
friend void swap(Class& x, Class& y) {}
};
でもこれでは既に他の名前空間にあるswapを特殊化できない罠。
なんかおかしくない?
おかしいのは漏れ?
352 :
デフォルトの名無しさん :02/04/23 00:12
>>351 たぶん、キミがおかしい。
VC7 のことはよくわからんけど、ふつう swap は <algorithm> の中で
次のように定義されているはず:
namespace std{
template<class T> inline void swap(T& x, T& y) { … }
}
で、何か標準ヘッダーをインクルードして、using namespace std;
してるでしょ? それで、1行目の swap とバッティングしてるんだと
思うけど。
ちなみに、2行目の swap は関係ない。それを外してもエラーが出るん
じゃない?
お手軽だからって using namespace std はやめよーよ。
354 :
デフォルトの名無しさん :02/04/23 01:08
>>352 例が悪かった・・
swapじゃなくてなんでもいいです。
とにかくテンプレート関数をクラステンプレートで特殊化しようとすると
特殊化優先順位で弾かれる。
名前空間とは関係ない問題です。(これが後々関係してくるが)
355 :
デフォルトの名無しさん :02/04/23 01:18
具体例を書くよ template<class T> class Class {}; template<class T> void func(T& x, T& y) {} template<class T> void func(Class<T>& x, Class<T>& y) {} void main() { Class<int> x, y; func(x, y); } error C2667: 'func' : 2 個のオーバーロード関数があいまいで最適な変換ができません。 で、 template<class T> class Class { public: friend void func(Class& x, Class& y) {} }; template<class T> void func(T& x, T& y) {} これならOK。VC7のSTLもこのパターンで実装されてる。 でも例えばfuncとClassが違う名前空間にあると このパターンは成り立たない。色々試したがダメだった。 具体的にはstd::swapなんかを 自作のテンプレートクラスで特殊化しようとした場合なんかに 困るわけなんだな、これが。
356 :
デフォルトの名無しさん :02/04/23 02:09
なんか、テンプレートでいくらがんばっても あんまり実りが無い感じ。
>>355 前半部分、13.5.1(p.404) によって後者が選ばれなきゃいけない話?
gcc 2.95ではちゃんと選ばれたよ。
358 :
デフォルトの名無しさん :02/04/23 10:39
>>357 C++の本を見る限りではそのgccの動作が正しいと思うんだけど。
VC7では選ばれる以前にコンパイルエラーになる。
多分、テンプレート関数とクラステンプレートで特殊化したテンプレート関数の
特殊化優先順位が等しいからこんなことになる。
これだったらすぐ直りそうなもんだからSPで直してほしい・・
359 :
デフォルトの名無しさん :02/04/23 12:34
メーカーの製品がこの程度の品質って、 C++のテンプレートの仕様を把握するのが一苦労って事なのかな?
上記の話、VC6でも確認。前からああみたいだ。 違う名前空間の関数を特殊化するなという意味だろうか。 Javaみたく階層的に名前空間分けてたら 同一プロジェクトでも同じ問題が発生するが・・ 共通関数を使わずメンバ関数を使えという話になるんだろうけど それだとSTLのうまみも半減だわな ところでクラステンプレートをクラステンプレートで特殊化って C++的に可能なの?VCではダメだった。
gccは3.0になってからその辺の構文的な要素は完全対応してるのかな?
>>355 Borland-C++ 5.6では正しくコンパイルできますた。
SDLがブレーク? フン、しねーよ。少なくともあなたには必要ないと思われ。
364 :
デフォルトの名無しさん :02/04/26 15:16
age
Lokiマンセー!!! でDLしたらVC.NETじゃコンパイルできねージャン!! 氏ねMS!IDEばっか凝ってねーでコンパイラ改良しる!
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄」 ―――――――――――――‐┬┘ | ____.____ | | | | | | | ∧_∧ | | C++を窓から投げ捨てろ | |( ´∀`)つ ミ | | |/ ⊃ ノ | | C++  ̄ ̄ ̄ ̄' ̄ ̄ ̄ ̄ | --------------------------------------------
>>365 そもそもMSがcl.exeをANSIに完全対応させる気がないのだとしたら
どういう事態になるんだろう。
ANSIが規格をねじ曲げれば一件落着。
369 :
デフォルトの名無しさん :02/04/30 22:06
関数ポインタの配列とenumの関係で質問です。 enum {HOGE,MOGE,MONA,SAGE}; void hoge(void); void moge(void); void mona(void); void sage(void); typedef void (*FUNC)(void); FUNC func[] = {hoge,moge,mona,sage}; こんな感じで、HOGEのときはhogeを呼ぶ、みたいに対応させてます。 このとき、enumの順番を変えたら、それに応じてfunc内の関数順番を 手動で変えるのがわずらわしいのです(enumとfuncは別ファイルです。 includeして、見えるようにはなってますけど)。 enumの順番に沿って、対応する関数がfunc内で自働的に並んでいて欲しいのです。 コンパイル時点では順番は確定しているんですから、テンプレートを ごりごり使いこなせる人間ならできるんじゃないかと淡い期待を 持ってるんですが、どうにかして出来ませんでしょうか?
無理 不可能
数が多いなら、excelのシートに関数名とenum識別子をかいといて VBAかなにかでボタン一個でソース吐くようにしとけば? 俺だけかもしらんが、よくやってるよ。 その場限りならセルに文字列適当に連結する式かいてコピペ、とかもやるし。
なぜ順番を変えるのかは突っ込まないで置こう。 見栄えが気にくわなくてあっち入れ替えたりこっち動かしたりする時期があるもんさ。
perlスクリプトで自動で吐くようにすればいいやん
ちょっと面倒だけど、こんなん駄目? #include "stdafx.h" template< int > struct Function{}; #define DEF_FUNC( index, func ) template<> struct Function<index>{ \ static void call(void){ func(); } } enum {HOGE,HAGE,}; void hoge(){puts("hoge");} void hage(){puts("hage");} DEF_FUNC( HOGE, hoge ); DEF_FUNC( HAGE, hage ); int main(int argc, char* argv[]) { Function<HOGE>::call(); Function<HAGE>::call(); return 0; }
ガーン! 今頃気づいたけど、呼び出し時のインデックスはコンパイル時には確定してないのか・・・じゃ駄目だ。
上のを修正。 ちょっとオーバーヘッドがあるけど、 (テンプレートクラス内のcallをfuncへのポインタに出来ればいいんだろうけど、俺はやり方知らない。) void (*funcs[])(void) = { Function<HOGE>::call, Function<HAGE>::call }; int main(int argc, char* argv[]) { for( int index = HOGE; index<=HAGE; ++index ) { funcs[index](); } return 0; }
> void (*funcs[])(void) = { > Function<HOGE>::call, > Function<HAGE>::call > }; それだと結局、enumを enum {HAGE,HOGE,}; に変えられたときにマズーではないか?
ぐわぁ! やっちまった(藁
>>375-377 ちょっとなぁ、という気がする。
自分が書くにはいいが、人には見せられない。
そもそも、見栄えを気にする(順番を入れ替える)んだから、
その書き方はいいとは思えない
こら待て、今気づいたんだが、375でいいじゃねぇかよ。 enum値と対応させるってことは配列のインデックスは手打ちでenumの値を書くってことだろ? インデックスが実行時に決まるならenumに対応させる意味もないし。
enum { HAGE, HOGE, }; template<int i> void f(); template<> void f<HAGE>() { return; } void f<HOGE>() { return; } void (*func[])() = { f<HAGE>, f<HOGE>, };
あ、ダメやん・・・(鬱
Modern C++ のInt2Typeとかをみてると、なーんかできそうな気がしてくるんですよねー。
どうやればいいのかはさっぱり分かりませんけど。
>>382 いや、呼び出すときは (*func[n])() ですが…。
対応させる意味がない…? えーと。考えます。
おいおい、じつはCOMだから関数の順序が....とかなんとか理由つけてくれよ
えーとですね。ふたつの実行ファイルが、enum値に依存してるわけなんです。 エンコーダとデコーダを作ってまして。 エンコーダは、テキストの文字列 "hoge" "hage"を読み込んで、 バイナリでenum値「HOGE,HAGE」を吐きます。んで、 デコーダは、バイナリでHOGE,HAGEをみて、関数hoge(),hage()を呼ぶ、と。 そういう状況です。 >>テーブルを動的に いや、いいんですけど。でも、静的に解決できることじゃないですか。 出来たらかっこいいじゃないですか。そういうスレじゃないですか、ここは。
>>389 もし出来たとしても決してかっこよくはならないと思うぞ。
#include <iostream> using std::cout; using std::endl; enum {SAGE,MONA,MOGE,HOGE, END}; // ←ここ順番変えてよし! typedef void (*FUNC)(); void hoge() { cout<<"hoge"<<endl; } void moge() { cout<<"moge"<<endl; } void mona() { cout<<"mona"<<endl; } void sage() { cout<<"sage"<<endl; } template<int> inline void f() {} #define ASSOC_FUNC(E,F) template<> inline void f<E>() { F(); } ASSOC_FUNC(HOGE,hoge) ASSOC_FUNC(MOGE,moge) ASSOC_FUNC(MONA,mona) ASSOC_FUNC(SAGE,sage) FUNC func[] = { f<0>, f<1>, f<2>, f<3> }; int main() { for( int i=0; i<END; ++i ) func[i](); return 0; } …と思ったんだけど、関数ポインタ経由だからinline展開されないよなぁ、これ…。
文字列からenum値に変換するのか? それだったら、 std::map<std::string, void(*)()> m; m["hoge"] = hoge; これでいいじゃん。
文字列->定数で解決したいんだろう 試みとしてはおもしろいかな。 でも、おれの知識じゃまだ無理だなあ。 Modern もっとよむか
なんかみんな無理してるよね(w それがもの凄く伝わってくるスレ
>>391 改造してみた、本末転倒?
#include <iostream>
using std::cout;
using std::endl;
enum {SAGE,MONA,MOGE,HOGE, END}; // ←ここ順番変えてよし!
#define sage f<SAGE>
#define mona f<MONA>
#define moge f<MOGE>
#define hoge f<HOGE>
typedef void (*FUNC)();
template<int> void f() {}
template<> void sage(){cout<<"sage"<<endl;}
template<> void mona(){cout<<"mona"<<endl;}
template<> void moge(){cout<<"moge"<<endl;}
template<> void hoge(){cout<<"hoge"<<endl;}
FUNC func[] = { f<0>, f<1>, f<2>, f<3> };
int main()
{
for( int i=0; i<END; ++i )
func[i]();
return 0;
}
もはやかっこよさなんてどうでもいい罠
かっこよさ以前に、ちゃんと動作してくれないんですが…。VCのせい?
>>396 Modern(の前半)読んでかっこいいと思ったか?
俺は、すげぇとは思ったがかっこいいとは思わなかったよ(むしろ汚い)。
このスレで今やってることも同じようなもんさ。
おとなしく動的作成にしない389が悪い。
>>398 #include "stdafx.h"
をソースファイルの先頭に入れ忘れてるとか。
関数テンプレートのテンプレートパラメータに定数を使うのは、 VCだとバグのせいでうまくいかなかったはず。 たしか、すべて同一の実体を指すようになってたような。
そういえばそうだったな。 他のに乗り換えれ。
#include <iostream> template <int i> void func() { std::cout << i << std::endl; } int main() { func<0>(); func<1>(); return 0; } これをコンパイルしてみればわかる
結局、VC(6以下)使ってる限りは無理って結論でよろしいか?
両方とも 1 が出力されました…。 (T_T)
関数テンプレートにせずに、クラステンプレートにすればいいやん。 template<int i> class func { public: func() { std::cout << i << std::endl; } };
すげー見にくくなってきたな・・・
たしかにクラステンプレートならVCでもいける…。 で、あとは391と組み合わせれば…?
コンパイルが通らない…。(T_T) どうすれば…。
>>409 ヒント
enum {
HAGE,
HOGE,
};
class FuncBase {
public:
virtual void operator()() { }
};
template<int i> class FuncObj;
template<>
class FuncObj<HAGE> : public FuncBase {
public: void operator()() {
std::cout << "hage" << std::endl;
}
} hage;
template<>
class FuncObj<HOGE> : public FuncBase {
public: void operator()() {
std::cout << "hoge" << std::endl;
}
} hoge;
FuncBase* func[] = {
&hage,
&hoge,
};
int main()
{
(*func[HOGE])();
(*func[HAGE])();
return 0;
}
テーブルに登録するところをいじってくれ
正直、
>>410 みたいにしてまでコンパイル時に決定したいとは思わないが。
とりあえずなんでもかんでも関数オブジェクトにしちまうか.... 最悪だな
はっきりいって、ここまでしてやることじゃないと思う
やっぱり、動的にテーブルを作るのが一番って事で、 ********************** 終了 ************************
出来ました!
>>395 にはかないませんけど、
>>391 より効率よく、なおかつVC6でも動きます。
#include <iostream>
using namespace std;
enum{HOGE,MOGE,HAGE,SAGE};// ←順番は任意に入れ替え可能
void hoge(void){cout<<"hoge"<<endl;}
void sage(void){cout<<"sage"<<endl;}
void moge(void){cout<<"moge"<<endl;}
void hage(void){cout<<"hage"<<endl;}
typedef void (*FUNC)(void);
template<int v>
struct f{
static FUNC f_;
};
#define ASSOC_FUNC(A,B) template<> FUNC f<A>::f_ = B;
ASSOC_FUNC(HOGE,hoge)
ASSOC_FUNC(HAGE,hage)
ASSOC_FUNC(SAGE,sage)
ASSOC_FUNC(MOGE,moge)
#undef ASSOC_FUNC
FUNC funcTable[4] = {f<0>::f_ ,f<1>::f_ ,f<2>::f_ ,f<3>::f_ };
int main(int argc, char* argv[])
{
for (int i=0;i<4;++i)
(funcTable[i])();
return 0;
}
初期状態よりも何倍も汚くなっている罠
まさに自己満足以外の何者でもない
プログラムの半分は自己満足で出来ています。
自己満足っつーか、ひとりよがり、って感じ。
うえーん、一生懸命考えたのに、ボロクソ言われてるよー
 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
∧_∧
( ´Д⊂ヽ
⊂ ノ
人 Y
し (_)
(´-`).。oO(っていうか、考えついたのが満足であって、
>>415 を使ったりはしないけどね…)
(´-`).。oO(.NETなら
>>395 を使えるのかしら?)
とりあえず、よくやった。 でも誰も使うことはないだろう。
筋トレと同じ。 これが実戦と同じだと勘違いしたら問題だが、 こういう鍛え方でしか鍛えられないことはある。 どんどんやるべきだと思うよ。
見せるため、自己満足のための筋トレと 運動するための筋トレはまったく別物。 鍛え方を間違っちゃいかん。
424 :
デフォルトの名無しさん :02/05/02 09:52
八頭身の予感 age
ポリシーやらファンクタやらを勉強ししてて、ふとこんな構文が 通ることに気付いてしまいました。 #include <iostream> using namespace std; class Hoge { public: void operator()(void){cout<<"hoge"<<endl;} }; int main(){ Hoge()();// ←なんと奇怪な構文! return 0; } …うわー。これ、ホントに通っていいんですか? まあ、理屈には合ってますけど…。 (最初のカッコでHogeのデフォルトコンストラクタでテンポラリインスタンスを生成。 次のカッコでHogeのoperator()を呼び出す) VCだけじゃないことを祈りまふ…。 ちとスレ違いかな。sage.
>>425 それ、普通だが?
文が完了するまで一時オブジェクトの寿命が続くはず。
Hoge(), foo(), bar();
こうすると、bar()の後にHogeのデストラクタが呼ばれる
いや、奇怪だっつーてるのは、カッコが連続してることです。 コンストラクタやoperator()の引数次第で、関数宣言だとか 関数ポインタだとか、そのあたりと間違えてしまいそうな構文だなーと。
関数オブジェクトを作り始めれば、別に不思議に思わなくなるよ。
>>425 struct Hoge { Hoge& operator()(void){return *this;} };
int main() {
Hoge()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()();
}
…はともかくとして、何の変哲もないふつうの構文だと思うよ。
> 関数宣言だとか関数ポインタだとか、そのあたりと間違えてしまいそうな構文
引数付きのコンストラクタを呼び出したりする時に、
下手すると関数宣言扱いになっちまうことはあり。
Effective STLとか参照。
430 :
デフォルトの名無しさん :02/05/03 03:37
>>425 それ、Cでも通らん?
#include<stdio.h>
typedef void (*fp)(void);
typedef fp (*fpp)(void);
void hogegege(void)
{
printf("\nhogegege\n");
return;
}
fp hogege(void)
{
printf("\nhogege\n");
return(hogegege);
}
fpp hoge(void)
{
printf("\nhoge\n");
return(hogege);
}
int main (int argc, char argv[])
{
hoge()()();
return(0);
}
----
/tmp>gcc hoge.c
/tmp>./a.out
hoge
hogege
hogegege
/tmp>
>>430 の登場によって、
>>425 のささやかな期待は、崩れ去ろうとしている。
しかしそれはC++信望崩壊への、ほんの序曲でしかなかった──────。
425「げ、良く考えたらどれもこれも、Cで作れるじゃん!」
430「それ、Cでも通らん?」
413「はっきりいって、ここまでしてやることじゃないと思う」
426「それ、普通だが?」
425「し、Cマンセー!C++なんてクソ。これ定説!」
だれかprojクトX風に仕立ててくれ。
( ̄ ̄< / ̄> \ ヽ / /ソ プ ロ ジ ェ ク ト\ ヽ P r o j e c t X ───────────────────── Generatorたち /|_/ /\Generators | / \ 丶 \/ \__ノ Genericスレッド。 このスレで425は一人で悩んでいた。なぜこんな構文が許されるのかと。 「いや、関数オブジェクトでは当たり前だ。」 「こんな物は普通だ。」 次々とヤジが飛ぶ。へこんだ。 万策尽き果てたとき、ふと430が現れる。 「Cでも出来るんじゃないか?」 これは、C++に翻弄された男たちの物語である。 風の中のスバル〜♪
まぁ変な書き方とかは狙えばいくらでもできるからね 1+-+-+-+-+-+-+-+1 とか
ぜんぜんgenericじゃない。
>>431 一応、マジフォロー。
Hoge()()()
がCでも関数ポインタを使えば構文上は通るとは言っても、
もちろん単なる関数ポインタと関数オブジェクトでは意味合いは大分違う。
たとえば、ベキ級数アルゴリズムを抽象化したクラスを考える:
class PowerSeries {
private:
int n;
double* coef;
public:
PowerSeries(double* coefficients, int number_of_coefficients)
n(number_of_coefficients), coef(coefficients){;}
double operator(double x){
double rst = coef[n];
for(int i = n - 1; n >= 0; i--){
rst *= x;
rst += coef[i];
}
return (rst);
}
};
このように関数オブジェクトではコード(級数計算アルゴリズム)に対して
それをカスタマイズするようなデータ(係数データ)を付加することができるが、
関数ポインタではできない。
この例は一種のCurry化であるが、一般にこのようなことを記述するには
「データを付加できる関数ポインタのようなもの」が必要になる。
もし高階関数型言語ならば、関数を返り値として関数クロージャーを利用すれば、
クロージャーにこのようなデータを記録できるが、C/C++には
高階関数がないので関数オブジェクトが必要となる。
Genericプログラムにおける関数オブジェクトの効用もそこにある。
>>435 スマン。名前間違えた。425じゃなくて430でした。
その上、間違えてageてるし・・・・・・。
さらにミスが。やっぱコンパイラ通すのサボっちゃだめスカねぇ。 誤>double operator(double x){ 正>double operator() (double x){
でも、たとえばSTLのalgorithmに関数オブジェクトを渡すと、 コピーを渡すことになるのでクロージャのデータは破棄されることになる。
うげ、さらにミスが。 誤>ベキ級数アルゴリズムを抽象化したクラス 正>ベキ級数を抽象化したクラス(評価にホーナーのアルゴリズムを使う)
>>438 C/C++のオブジェクトの代入セマンティクスでは
デフォは参照じゃなくてコピーざんすからねぇ。
受け渡したいデータの性質と意味に応じてコピー・コンストラクタあたりで
なんとか頑張るしかないでしょうなぁ。
>>440 参照カウントやGCライブラリを使うという選択もあるかもしれないけど。
悩める愚者より識者にしつもーん std::transformに渡す関数オブジェクトって副作用があっちゃダメってことですけど、 これの具体的な根拠ってどこにあって、 実際どういう不具合が考えられるのかわかりますか? 状態変数のようなものを内部に持てるのが関数オブジェクトのいいところだと 思っていたのですが、これはつまり、副作用を期待して呼び出す std::for_eachと はちがって操作対象の変換(のみ)を純粋に扱うstd::transformが呼ぶ関数オブジェクト は副作用があってはいけない、といういみでしょうか。 たとえば、 呼び出されるたびに内部カウンタをインクリメントした値を加算する変態加算関数オブジェクト struct addinc : std::unary_function<int, int> { addinc(int serial = 0) : serial_(serial) {} int operator()(int n) { return n + serial++_; } private: int serial_; }; みたいなのは、transformに対して使用するには不適切、ということでしょうか? それとも関数オブジェクト呼び出しがconstかどうかが問題であって、 int operator()(intn)をconstメンバに、int serial_をmutableとかにしちゃえば セマンティクス的にもOKというわけなんでしょうか?
443 :
デフォルトの名無しさん :02/05/05 00:28
age
>>442 > std::transformに渡す関数オブジェクトって副作用があっちゃダメってことですけど、
これ初耳なのだがどこに書いてあったん?
標準テンプレートライブラリによるC++プログラミングの二版の22.16.3の最後に書いてあるんです。 今SGIのSTLのドキュメントを読みましたが、そんなことは書いてないですね。
>>442 Effective STL 39項がそのものズバリの解説になっている気がする
はうう、後で読み直してみます。 ありがとーございましし。
手元にあるC++標準テンプレートライブラリをざっと読む限りだと: この場合言われてる「副作用」は厳密な参照透明性 (、内部状態変数やグローバル変数への代入、入出力禁止とかを含む) とかじゃなくて、与えられた引数(イテレータ)の指すオブジェクトを 書き換えてはイカンということなんじゃ?
>>449 C++標準テンプレートライブラリ
は
The C++ Standard Template Library
(P.J.Plauger他著、)の邦訳(ピアソン・エデュケーション刊)ね。
>>449 transformがじゃなくてオペレーターがね。>書き換え禁止
>>449 そんな気がする。
Effective STL で取り上げられてたのは Item 37 の std::for_each と
std::accumerate の話じゃない?
>>447
>>452 チェックしてみたらご指摘の通りでした。すんません。
ありがとうございましし。
>>449 =430さんのおっしゃるような意味だと解釈しましし。
455 :
デフォルトの名無しさん :02/05/07 04:41
Lokiの存在を知って以来VCでの開発が苦痛だ・・・
>>455 マジで?
実際にLokiなんか使う場面あるか?
>>456 俺様ライブラリを作るときとか。
Lokiのすべてとは言わないが、カスタマイズ可能なスマートポインタ(他)はホスィ・・・
LokiはA.Alex.の壮大なネタだ
Lokiって実用ライブラリじゃなくてストレステストでしょ といってみるテスツ
>456 SingletonHolderは使ってますが何か?
誰か話題振れよう。 || (
>>303 漏れにも教えて)
どなたかallocator<>の使い方教えて下さい。難しすぎる・・・・・
T型オブジェクトの配列のためのメモリ管理用テンプレート? がんばれー
T型オブジェクトの配列のためのメモリ管理用テンプレート? がんばれー
>>458 は名言だと思う。
というかほんとにそんな気がしてならない。死のう・・・
あの人、コンパイラメーカーで働いてるの?
学生ちゃうん?
各コンパイラメーカーのテンプレートサポートが落ち着いてくれば Lokiで使われているテクニックが次のスタンダードに導入されるだろう事は まず間違い無いと思われ。
>>471 一部は使われると思うが、使わないネタも多いんじゃないかなぁ……。
TypeListは必須だな
それはない
どう考えても浸透しそうなのはポリシーのみ。 それ以外は実務で役立つかというと(?)
a
aa
aaa
Typelistのとこで、58ページの下に、「コードに繰り返しを 含める事なく、配列を初期化することもできます」ってあるん ですけど。これって、どうやるんですか?
age.
>>480 読んだ事ないけどstd::fill使うとか?
>>482 fillじゃ無理っしょ。
単なるforループなんだから
試しに繰り返しを使わず配列の初期化をやってみよう。 template <int i> class A{ public: template<typename T> static inline void foo(T* p){ *p = 0; A<i-1>::foo(p+1); } }; int x[10]; A<10>::foo(x); これでどうだ。・・・あんまり意味なさげ。
485 :
デフォルトの名無しさん :02/05/11 00:17
>>485 お前、頭大丈夫か?
もうだめぽ・・・(-_- )
>>484 最高だ!応用すればループがインライン展開されるfor_eachとか書けそう!
>>487 だめだよ。大抵のコンパイラはtemplateの展開可能レベルが浅い。
最近のコンパイラは最低限のunrollは行ってくれる 最近のCPUはunrollするとキャッシュのミスヒットでパフォーマンスが低下する
>>490 unrollする量でチューニング。
テンプレートを利用した行列計算でメモリ階層を意識して
ブロック化、ループ展開などの最適化を施した例としてMTLがある。
>>484 いや、Typelistのとこでの話なんですから、コンパイル時に初期化が
終わるんじゃないかと。
このやり方だと、実行時に初期化してますよね。
この58ページの雰囲気的には、 std::type_info* intsRtti[Length<SignedIntegrals>::value] = { TypeAt<SignedIntegrals,0>::Result, TypeAt<SignedIntegrals,1>::Result, TypeAt<SignedIntegrals,2>::Result, TypeAt<SignedIntegrals,3>::Result, // Lengthの示す長さ分だけ続ける… } これを、コンパイル時に自働的に解決するための汎用性のある書き方が存在する、 ってことだと思うんですよ。 …どうすりゃいいんでしょうね。
配列の要素が静的に初期化できる構文といえば double a[3] = {1.0 ,2.0 ,3.0}; だが。テンプレートから生成できるとは思えんしなー。 まさか、 template<class T, int N> struct A { T d = T(N)/*constant expression of N*/; A<T, N-1> succ; }; template<class T> struct A<T,1> { T d = T(1)/* constant expression */; }; template<class T, int N> const T* getArray(const Struct<T,N> s) { return((T*)(&s)) } なんてこたないよな。 仮想メンバ関数もなく継承とかもしてないstructはCの構造体と互換だが……。 移植性あるか?(alignment調整のpackingとか。)
>>494 今、手元にコンパイラがないんで未テスト。スマソ。
>>494 ごめん。packing -> padding
//さすがに動かなかったよ。 #include<iostream.h> template<int N> struct Init { static const double data = Init<N-1>::data * double(N); static const Init<N-1> succ; }; template<> struct Init<1> { static const double data = 1.0; }; template<int N> inline const double* getArray(const Init<N> a) { return((double*)(&(a))); } Init<5> init; const double* a = getArray(init); int main(int Argc, char* Argv[]) { cout << "\n"; for(int i = 0; i < 5; i++) { cout << " " << a[i]; } cout << "\n"; cout << init.data << " "; cout << init.succ.data << " "; cout << init.succ.succ.data << " "; cout << init.succ.succ.succ.data << " "; cout << init.succ.succ.succ.succ.data << " "; cout << "\n"; return(0); }
>>497 ↑はコンパイルは通るけど結果は思ったようにならない。
結果:
4.85246e-270 2.96439e-323 5.08888e-322 1.58101e-322 4.85634e-270
120 24 6 2 1
ある意味ホっとした。
>>497 ・・・えーとさぁ。突っ込んでいいかなあ?
> return((double*)(&(a)));
ここでアドレス取ってるけど、これって getArray の引数 a のアドレスだよなぁ?
getArray の引数 a は getArray の終了時にスタックから消滅してるから、
そのアドレスを戻り値として返すのは不正なんじゃなかろうか。
それと、Init<5> の非スタティックメンバって何もないから、
sizeof(Init<5>) = 0 (あるいは 1)のはずで、
それを double にキャストして逆参照してもゴミ値なんじゃないの?
501 :
デフォルトの名無しさん :02/05/12 15:31
std::iterator_traits<int*>::value_type val; C++スレに書かれてたやつだけど、なんかこっちのほうがふさわしそうなんでこっち持ってきた。 VC++6でコンパイルエラーだそうです。 VC++.NETでコンパイルしたら > xutility(98): error C2825: '_Iter::iterator_category': 限定名を形成できません。 > xutility(98): error C2039: 'iterator_category' : 'operator``global namespace''' のメンバではありません。 > xutility(98): fatal error C1507: エラーが多すぎてコンパイルを継続できません。 って言われた。 ツールチップの型ヒントではちゃんとintのtypedefになってるんだけど、 なぜコンパイルできないんでしょう?
>>502 501じゃないけど、g++ならふつうに通るみたいだよ。
調べてみました、VC++のコンパイラの能力ではiterator_traitsをポインタに対して特殊化することが出来ないんですね。 そのため特殊化されていない形式のiterator_traitsを構築しようとしてコンパイルエラーが出ているようでした。 STLのソースの中でもiterator_traitsはほとんど使用されていませんでした。 Genericの中に書かれている古いタイプの方法に近い形で実装されているようです。
ああ、まだ上には上がいるんだな。 勉強が足りなかった。
>>303 これってどういう意味? 8章を読んだけど全く理解できなかったってこと?
それとも、全部理解したけど期待した程じゃねーぞゴルァ、ってこと?
508 :
たんなる雑談 :02/05/16 10:17
画像の描画処理にPoplicyを使うことにしました 描画処理は ・速度が要求される ・透過、拡大、反転など組み合わせ次第で処理の量が膨大になる ということでPolicyの考え方にまさにベストマッチですが、 どこをPolicyクラスにしてどこをtemplateクラスにするのかの判断はやっぱり難しいですねぇ。 Policyの境界を越えた最適化が出来ないというのもちょっとネックになりそうです。
>Policyの境界を越えた最適化が出来ないというのもちょっと これは層化の設計の問題でしょ。 下層で問題になるなら上層のPolicyをごっそり入れ替えればよし。 余談:Policyテクニック自体はSTLが存在するころから存在してるよね。 STL自身が使ってるから。
う〜〜ん使いこなせるようにはまだしばし時間が必要(^^;
511 :
デフォルトの名無しさん :02/05/16 21:03
513 :
デフォルトの名無しさん :02/05/16 21:29
>>511 ほんの一部なら動くがほとんどはダメです。
LokiのキモであるところのTypeListは
テンプレートの部分的な特殊化を前提に組まれてます。
再帰的な処理、その終端の特殊化もその機能に依存してます。
そしてVCでは部分的な特殊化はサポートされません。
これはヘルプにはっきり書いてあります。
514 :
デフォルトの名無しさん :02/05/16 21:38
じゃあだめじゃん。 クリティカルな問題が無くならないね。 もうちょっと単純な仕様にすればいいのに。>テンプレート
↓これどうなん? Q: 他のC++ ツールで、より標準に適合しているものはありますか? JON CAVES: はい、Visual C++よりも標準に適合するC++ コンパイラはあります。 1つの例は、私が100%適合していると信じるEdison Design Group (EDG)によるコンパイラです。 ただし、このコンパイラはWindows プラットホームではあまり利用できませんが。 Windows プラットホームではやはり、Visual C++が最も標準に適合するコンパイラの1つです。
>>515 一長一短ではあるけど、
gcc3 、CodeWarrior7、 bcc5.6 (C++Builder) 辺りは
VC6よりは遙かに標準に近い気がする。VC.NETだとどうなんだろ?
それに、EDGのフロントエンドも100%とは思えないが…。
517 :
デフォルトの名無しさん :02/05/16 22:15
VC.NETのテンプレート機能はVC6と大差ないです。 テンプレートパラメータがサポートされた程度。 てゆうかLokiコンパイルできません。
>>517 >テンプレートの部分的な特殊化
はどうなの?
VC6と変わりません。つまりダメ。
>>513 はVC.NETでの話。
テンプレートの部分的な特殊化は実装がなかなか複雑なようで その優先順位の判断にパターンマッチングやらなんやらが必要らしいです。 しかしModernC++によって部分的な特殊化がほぼ別物といっても良いくらい 飛躍的な表現力の向上につながることが明らかにされたわけなので 今後積極的にサポートされていく可能性は高いでしょう。
ModernC++はほんとパラダイムシフトだよね。 あれでコンパイラメーカーの奮起を期待したいところだね。 VC++に関してはどうなんだろう。MSやる気あんのかなぁ。。 個人的には.netでのアクロバットなテンプレートサポートに 期待してるけどね。
>>522 Adobe Acrobat.NET(テンプレート付き)
ワロタ
gcc 3.1 でてるね。
526 :
デフォルトの名無しさん :02/05/17 08:58
C++じゃ無くても良いんじゃないのかな。
デキタ━━(゜∀゜)━( ゜∀)━( ゜)━( )━(゜ )━(∀゜ )━(゜∀゜)━━!!!!! 拡大反転透過楕円半透明コピーが出来たときには感動した!! 馬鹿正直に書いてたら数千〜数万行のコードがたったの500行ですんだ、すごいYO!!
528 :
デフォルトの名無しさん :02/05/17 19:32
『Moder C++ Design』を読んでいるのですが、 公式サイトからダウンロードしたソースに、バグらしきものを発見しました。 該当個所は、第四章で紹介されているFixedAllocatorのVicinityメソッドです。 SmallObj.cpp の中で以下のようになっていますが(左は行番号)、 271: Chunk* lo = deallocChunk_; 272: Chunk* hi = deallocChunk_ + 1; 273: Chunk* loBound = &chunks_.front(); 274: Chunk* hiBound = &chunks_.back() + 1; もし deallocChunk_ が &chunks_.back() と同じ値であった場合、 290: if (p >= hi->pData_ && p < hi->pData_ + chunkLength) この hi が指しているのは範囲外の要素となってしまいます。 これは既知のバグなのでしょうか。 参考までに VicinityFind メソッドを全文引用しておきます。 264:FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p) 265:{ 266: assert(!chunks_.empty()); 267: assert(deallocChunk_); 268: 269: const std::size_t chunkLength = numBlocks_ * blockSize_; 270: 271: Chunk* lo = deallocChunk_; 272: Chunk* hi = deallocChunk_ + 1; 273: Chunk* loBound = &chunks_.front(); 274: Chunk* hiBound = &chunks_.back() + 1; 275: 276: for (;;) 277: { 278: if (lo) 279: { 280: if (p >= lo->pData_ && p < lo->pData_ + chunkLength) 281: { 282: return lo; 283: } 284: if (lo == loBound) lo = 0; 285: else --lo; 286: } 287: 288: if (hi) 289: { 290: if (p >= hi->pData_ && p < hi->pData_ + chunkLength) 291: { 292: return hi; 293: } 294: if (++hi == hiBound) hi = 0; 295: } 296: } 297: assert(false); 298: return 0; 299:}
264:FixedAllocator::Chunk* FixedAllocator::VicinityFind(void* p) 265:{ 266: assert(!chunks_.empty()); 267: assert(deallocChunk_); 268: 269: const std::size_t chunkLength = numBlocks_ * blockSize_; 270: 271: Chunk* lo = deallocChunk_; 272: Chunk* hi = deallocChunk_; // ココ 273: Chunk* loBound = &chunks_.front(); 274: Chunk* hiBound = &chunks_.back() + 1; 275: 276: for (;;) 277: { 278: if (lo) 279: { 280: if (p >= lo->pData_ && p < lo->pData_ + chunkLength) 281: { 282: return lo; 283: } 284: if (lo == loBound) lo = 0; 285: else --lo; 286: } 287: 294: if (++hi == hiBound) hi = 0; // ココ 288: if (hi) 289: { 290: if (p >= hi->pData_ && p < hi->pData_ + chunkLength) 291: { 292: return hi; 293: } 295: } 296: } 297: assert(false); 298: return 0; 299:}
行番号ウザイ
return 0 は0行目に戻れな罠。
>>529 おー、これだとたしかになおってそうですね。
つうか、オレもなおしちゃったけど。
もし未知のバグなら、報告したほうがいいんですかね。英語わかんねえけど。
>>530 がんばって行番号つけたのにッ! BASICを使ってた思い出に浸っていたのにッ!
オレの思い出をこわさないでー!
>>531 んなわけねえだろ。だいたい0行目なんて存在しねえんだよ。
テメエはCのやりすぎだ。一日二回くらいにしといたほうがいいぞ。
>>532 訳者のページに行ってみてはどうか。
オンラインで直ってないなら未知と思われるので。
>>532 me fix bug. this patch
とか書いてdiff結果張り付けてメールとか。
528が常駐してからスレの雰囲気が悪くなったな
うむ
>>538-539 あら、雰囲気悪くなっちゃった? ユーモアってやつをわかってねえなあ。
ほれ、良書って言われる類の書籍には、たいていアメリカンジョークが書いてあるじゃん。
それもすっげーつまんないやつ。立派なプログラマなら、それで笑えるようになろうぜ。
理想としては、
>>537 の人みたいにソースコードを見ただけで
笑いがこみ上げてくるレベルを目指すべし。
>>540 面白くもないモノに笑えるほど出来た人間じゃないんでね。
キエロ
542 :
デフォルトの名無しさん :02/05/18 14:00
541<<<<<<<<<<<540
>たいていアメリカンジョークが書いてあるじゃん。 528のはそれ未満なので笑えません。
>>542 それはあり得ない。
常に541>540である
せめてIQが平均気温より高ければなぁ。
528って自分に自信のないデヴオタヒッキーなんだろうなぁ… なんか、某駄スレのJohnに酷似しているし。
Johnの方が小賢しいな
550 :
デフォルトの名無しさん :02/05/20 14:14
テンプレート使いまくりのコード書いたら コンパイル速度激しく遅くなったんですが(;´Д`) PCHにいれても入れなくても変わらず 自業自得ですけど・・・死ねるほどおそひ・・・VC.NET・・・
PCH使って死ぬほど遅いのは、9割方使い方がおかしいだけ。
ちょっとした短いコード(10行以内?)以外は インライン実装するべきじゃない。 デメリットのほうが大きい。 素直にテンプレートの具体的な特殊化か ポリモフィズムを使用するべし。
>>552 昔の実装と違ってinlineはregisterと同じくもはやヒントでしかないし……。
そうカリカリせんでもいいんじゃない?
(暗黙のstticの意味を除けば。)
ほっしゅほっしゅ
>>552 VC++の場合ちょっとでも大きいとインライン展開してくれないようです
3行くらいでもわりと複雑な計算してると展開されません
チョー速度が要求されるところだったから__forceinline使いましたが
差分コンパイルができない。= 依存関係のある全てのソースにリコンパイルがかかる。 また、インライン展開されなくとも複数の実体が生成される可能性もある。 そもそもインライン展開の判断自体、処理系依存である。 ちっこいプロジェクトなら問題ないかもしれんが 大規模ではちょっとした手抜きの割に被害はでかい。 テンプレートの使い方とその設計手法をまともに考えれば クソでかい関数はできないはず。
557 :
デフォルトの名無しさん :02/05/27 19:55
テンプレートだけ変換することってできない?
558 :
デフォルトの名無しさん :02/05/28 23:32
>>552 が言っていることがよくわからなんだけど、
inlineとexportしてない(できない)templateとtemplateの明示的特化って
別物じゃないの?
559 :
デフォルトの名無しさん :02/05/28 23:47
ああまだ上には上がいたんだな(´Д`) 出直そう
>ちょっとした短いコード(10行以内?)以外は
>インライン実装するべきじゃない。
>デメリットのほうが大きい。
ここは一般論でその理由は
>>556 >素直にテンプレートの具体的な特殊化か
>ポリモフィズムを使用するべし。
こっちは
>>550 に対してアドヴァイスしたつもりだった。
言葉足らずスマン。
テンプレート関数をexportできる処理系はまだ見たこと無いので
無いものとして話してる。
補足:
>テンプレートの具体的な特殊化
具体的な特殊化でテンプレート引数がすべて決まれば
普通のクラスと同じように非インライン関数として書ける。
テンプレートの用途からするとほとんど使えないテクだが・・
561 :
デフォルトの名無しさん :02/05/31 23:02
以下のようなテンプレートの特殊化がVC++(ver6)では通らないんですが 何が問題なのでしょうか?g++ならば通るんですが・・・。 template<typename T, typename U> struct test {}; template<class T> struct test<int,T> {};
>>564 ありがとうございます。ショックでかいです。
で質問なんですが.NETなら大丈夫とかないですか?
スレとずれて恐縮なんですが。
>>565 .NETでもダメです。
正直がっかりでしたがVC8に期待しましょう。
VCっていう前提が取れないところが素晴らしい
569 :
デフォルトの名無しさん :02/05/31 23:27
いまさらVC使う意味は無いと思うんだが。
570 :
デフォルトの名無しさん :02/06/01 00:05
VitaminC
571 :
デフォルトの名無しさん :02/06/01 00:37
お金が無いんだよ!!無職なんだから
お金がないならそれこそどうしてVC++?
VSのIDEでコンパイルだけgcc使えればいいのに・・・。
デバッグできないから意味無いじゃん
576 :
VC6に乗せたい :02/06/03 02:06
VS.NETが買えない貧乏人の私としては、VC6で何とか動かしてみたい。 template <class TList> struct Length { enum { value = 1 + Length<TList::Tail>::value }; }; template <> struct Length<NullType> { enum { value = 0 }; }; template <class TList, unsigned int i> struct TypeAt { template<int cnt> struct isEnd { typedef typename TypeAt<TList::Tail, cnt-1>::Result type; }; template<> struct isEnd<0> { typedef typename TList::Head type; }; typedef typename isEnd<i>::type Result; }; こういう風に書き換えればTypeListを使うことができるようになった。 既出ならスマソ
577 :
デフォルトの名無しさん :02/06/03 02:08
>>576 なんだかわからんけど、よくやった!
次もこの調子でたのむ。
578 :
デフォルトの名無しさん :02/06/03 02:31
>>576 よくやった!
ただ、
不明な型が厳密にひとつしかないクラステンプレートなら
部分的な特殊化を使わずに実装できるんだが
TypeListにはそうでない機能がいくつかあるんだよね。
VC++で無理やりSingletonHolderを動くようにしたんです。 って言ってもtemplateなstatic変数が作れないだけですから、 マクロ作って個々にインスタンスを作ってやっただけですけど。 で、ためしにLoki::SingletonWithLongevity使ってみたら GetLongevityの戻り値が大きいほうから先に削除されちゃうんです。 ここでまたぶち切れですよ。 ModernにはGetLongevityの戻り値が小さいほうから削除されるように書かれているのに。 これはどう解釈したら言いのでしょう。
>>576 VC++でSelectをなんとか出来ませんか?
昼頃出先で書き込もうとしたら、串が2ch鯖に知られてて書き込めず、激しく鬱。 それはさておき。 VC++6.0は、ご承知のようにクラステンプレートの部分的な特殊化を サポートしていません。 しかし、クラステンプレートの完全な特殊化はサポートされています。 [VC6で使えない例] template <class TA, class TB> struct baa{}; template <class TA> struct baa<TA, int> ← すでに定義されているというエラーが出る {}; [VC6で通る例] template <class T> struct baa{}; template <> struct baa<double> {}; あるいは、 template <class TA, class TB> struct tee{}; template <> struct tee<double, int> {}; これだけなら大したことはできないのですが、 これをTypeAtのように、クラス内クラスで使うことで、 事実上の部分特殊化を掛けることができるようになります。 現在、手元でIndexOf まで仕上げました。 私はファンクタとダブルディスパッチを使いたいと思っているので、 それらの実装を目指すことにします。
>>582 おぉぉ!
template< A, B, C >
の
Aだけ特殊化は出来ないから
template< A > class{ template< B, C > }
にしてAを特殊化するんですね!
Select行ってみます!
Selectはできたけんども
TypeAtNonStrictで見事に撃沈・・・
完成したら作者に報告とともにどっかにウプしてくれ・・・
>>583
583を訂正 template< A, B, C > struct { template< A > struct { //↑ここを特殊化するんですね } }
>>583 殿。
>>582 で示したガイドラインに沿ってTypeAtNonStrictを書いてみました。
あのように作り方を明記すると、考えが整理できるものですね。
>>576 で載せたテンプレートも、ガイドラインに沿った命名に書き換えました。
template <class TList, unsigned int index,
typename DefaultType = NullType>
struct TypeAtNonStrict
{
template <class tmpTList>
struct tmp2TypeAt
{
template <unsigned int cnt>
struct tmp1TypeAt
{
typedef TypeAtNonStrict<tmpTList::Tail, cnt-1, DefaultType>::Result Result;
};
template <> struct tmp1TypeAt<0>
{
typedef tmpTList::Head Result;
};
typedef tmp1TypeAt<index>::Result Result;
};
template <> struct tmp2TypeAt<DefaultType>
{
typedef DefaultType Result;
};
typedef tmp2TypeAt<TList>::Result Result;
};
このコードで、コンパイル、テスト動作ができることは確認しております。
願わくば、この勢いで TypeList.h で定義されている
テンプレート群をVC6仕様に書き換える作業にご協力願いたい。
正直、一人ではきついので。
>>587 で、今どこまで出来てるの?
協力しようにも何が出来てて何がまだなのか分からんと。
ただ、漏れ VC++ 持ってねぇんだよなぁ・・・
強力はおしまんですよ、TypeAtNonStrictすらできなかった漏れが役に立てるかどうかはわからんですけど、
>>587 の
下から6行目
> template <> struct tmp2TypeAt<DefaultType>
↓
> template <> struct tmp2TypeAt<NullType>
だと思います。
>>588 殿。恥ずかしながら、まだ IndexOf を実装しただけです。
本業もあるため、平日は遅々とした進度になるかと思われます。
できそうなところからどんどん発表していくつもりです。
あと、
>>589 の指摘ですが、原著の作者の実装をそのまま置き換えたため、
そのようになっております。元ソースと比較してみてください。
なお、先日から取り組んでいる Typlist 型関数は、
数値関数に置き換えれば、このようになります。
Result TypeAtNonStrict(class TList, int index,
class DefaultType = NullType)
{
if(TList != DefaultType)
{
if(index != 0)
{
return TypeAtNonStrict(TList.Tail, index-1, DefaultType);
}
else
{
return TList.Head;
}
}
else
{
return DefaultType;
}
};
元ソースよりもいくらか手続きっぽくなってるのかも。
age
しまった。タブの置き換えを忘れていました。スマソ Result TypeAtNonStrict(class TList, int index, class DefaultType = NullType) { if(TList != DefaultType) { if(index != 0) { return TypeAtNonStrict(TList.Tail, index-1, DefaultType); } else { return TList.Head; } } else { return DefaultType; } };
とりあえず私はtypelist.hの下から行きます。 今MostDerived終わりました。後でどっかでマージしませう あとtmpじゃ分かりにくいので名前付け方法を決めたほうがいいと思います。 私は template <class TList, unsigned int index, typename DefaultType = NullType> struct TypeAtNonStrict { template <class tmpTList> struct SelectTList { template <unsigned int cnt> struct SelectIndex { hogehoge... }; }; typedef SelectTList<TList>::SelectIndex<index>::Result Result; }; のようにしました
す、すげー。あんたら、すげーよ。完成したら、ぜひ使わせてもらうよ! がんばってっ!
ReplaceとReplaceAll終わりました つーか使っててすげーです、Lokiマンセー!!!
目から鱗すぎます。 素晴らしい。 第二版に日本人の名を連ねられるか?? 期待して待つ!
あー 漏れ私的に使いたかったTypeTraitsの移植に挑戦してみようかな・・・
Erase以降全て終わりますた
>>597 人が作ったものは作り直したくないので、終わったらここに報告してね。
漏れがLokiと格闘してる間にイタリア1点取ってるし・・・(´д`;
うぉ! もしかしてtypelist.h終わったじゃん。 どっかにウプしよーぜ!
sourceforge.comだと世界中から見つかりやすげ
>>601-602 使い方分からん・・・(´д`;
編集済みtypelist.hとtypemanip.h、
VC++用に改造したsingleton.hが入ってます。
http://www68.dns.ne.jp/~bbs2/upload3/helen/OB00011454.zip VC++.NETで作ったので、VC++6.0で動かなかったらゴメソ
なにぶん以前は動いてなかったので、typelist.hとtypemanip.hが元と同じように動作するかは確認できてません。
特にtypemanip.hのConversionが、exists2Wayが元と違う方法を使ってるので、その辺でばぐるかも。
編集後のSingletonHolderは残念ながら元と全く同じように使うことは出来ません、
これを使うときは、
プロジェクト内のCPPファイル内でImplementLokiSingletonマクロを使って
SingletonHolderのstaticメンバ変数の実体を作ってちょ
とにかく576は間違いなく神だな・・・
神の啓示を受けた気分だ。
おおおっ! ちょっと離席していた間にもう終わったのですか。すげー!
>>603 は早速ダウンロードして、すべてチェックしました。
今のところ、VC6でも正常に動作しているようです。
typename とはこういうものだったのですか。
これを知らずにAppendの実装がうまくいかず、一時中断していたのですが。
知らぬではどうにもならぬですね。まだまだ修行が足りないです。
勉強になります。
LokiPortよりも漏れらのやつのほうが美しいようだ、良かった良かった。
おりょ? やっぱりやってることはほとんど同じか・・・(鬱 (汚いと見えた)MakeTypeListやis_TypelistはLokiのバージョンアップで追加されたものかな?
>>583 その「is_Typelist」が、VC6ではコンパイラに通らないです。
結局、VC6にはtypename 指定をしないと、
template<typename Head, typename Tail>
Typelist<Head, Tail>
と
NullType の区別がつかないようなのです。
VC.NET用はともかく、VC6用は、ここで新規開発しないといけないかも。
>>598 ダメですた。
ポインタの特殊化がどーーーしてもできまへん。
と思ったら
>>604 で見事に実装されてますた。
悔しいやら嬉しいやら。
ともかく念願のTypeTraitsが手に入りますた。
ありがとうございます。
そういえばVCは なぜか前から関数テンプレートのポインタ等の特殊化を サポートしてるんだよな・・。 その調子でクラステンプレートも実装してホスィ
>>608 漏れはVC.NETなのでLokiPortに満足してしまいますた。
続きはがんばってください。
何かあれば協力しますし。
MakeTypeList age これがあるとがぜん使う気が起きるね!
>>608 まあ今時VC6でなにかしようというのが、もう時代遅れなのかもしれないですが。
>>609 LokiPort の MakeTypeList は単体で動作するようです。
>>583 氏のヘッダに移植できました。
あと、うっかりサンプルソースでReverseを呼び出すのを忘れていたのですが、
こいつがエラーが出てコンパイラにとおりません。(VC6)
ガイドライン通りにちゃんと書かれているようなのですが。原因はまだ不明です。
このスレの前のほう見るとLokiをVCで通るようにするのは絶対無理って書かれてるな。
>>613 はその発想力を大切にするといい。
ModernC++のページでもセンセーショナルだと書かれてるね>604 出てきたのが今年の3月だから、タッチの差は僅かだ。 MakeTypeList も上のほうで無理言われてたけどあっさり実装されちゃってる まるで魔法だ。 C++って奥深すぎる。鬱だ。
616 :
デフォルトの名無しさん :02/06/05 16:21
テンプレート乱用しすぎますた(´д`;) 1翻訳単位のコンパイルにジャスト3分(あんまり長いので測った まだ(やってることは)小さなプログラムなのにビルド後のファイルサイズは1MB突破・・・ テンプレート依存は一箇所に局所化して他の翻訳単位は高速化したけどそれでもつらいっす・・・
嘘くせー
ヽ(`Д´)ノナンダト!!
>>616 ひょっとしてポインタ型各種について展開してないか?
早速Lokiを酷使してるとか?
書き始めたころ(
>>508 くらい)はまだVCでLokiが動かせるとは夢にも思って無かったです。
画像の描画処理を転送・フィルター・形状・スケーリングの4つのポリシーに分けらああなりますた。
特に2つの転送ポリシーを合成するポリシーを作ったらコードサイズも時間も爆発。(まぁ当然か
転送をポリシーととらえるのはどうか。 ピクセルの特性をポリシーとするなら分かるが。
>>622 エフェクト、といえばよかったかも。
単純描画や飽和加算など
なるほど 某otakuのGTLの発展したような物ですね、 かっこよさそうです。
demo otaku はどこいっちゃったんでしょうか?
>>621 Effective C++で、void* で受けることで
テンプレートによって生成されるコード量を大幅に
減らすアイデアが載っていましたが、いかがか?
>>604 からスレの流れが変わったので、コテハンやめるっす。
>>626 Effectiveもってないっす、詳細きぼん
628 :
デフォルトの名無しさん :02/06/07 01:52
STLスレって倉庫落ち?
>>627 Modern C++ Designは Effective C++に書いてあることが前提になっているので、
先に読んでおいたほうがいいですぞ。買っても後悔しないです。
要は、コンテナに入れるものをvoid*として格納するコンテナを用意しておき、
要素に対する操作を定義しておきます。(ソートだとか何とか)
で、void*として放り込む作成・破壊クラスを別に定義します。
確かこんな感じだったはず。詳細は当該書籍を読まれよ。
632 :
デフォルトの名無しさん :02/06/07 13:37
既出の質問かもしれませんが、教えて下さい。 メンバー関数の有無によってコードを書き分けるにはどうしたら良いのでしょうか。 例えば、次のようなテンプレートクラスがあるとします。 template <class A> class X { void func() { if (/* A::foo() があるかどうかの判定*/) } /*CODE1: A::foo()を使う処理 */ } else { /*CODE2: A::foo()を使わない処理、もしくはA::foo()の処理を肩代りする処理*/ } } }; ここでクラスA1にはメンバー関数foo()があり、 クラスA2にはメンバー関数foo()がないとします。 このとき、X<A1>::func()とX<A2>::func()は それぞれCODE1とCODE2の部分だけ実行するようにしたいのです。 できれば、判定をコンパイル時に行ない、コンパイルされたオブジェクト にはコードが最適化されてCODE1とCODE2のどちらかしかしか 存在しないようにしたいと思っています。 こういうことは可能でしょうか? 可能だとするとどのようにしたら良いでしょうか?
>>632 C++にはリフレクション機能が無いので
特定メンバあるかどうかの判断はできない。(・・よね?)
だから他の条件が必要。
渡されるクラス全てにタグを定義とかの制限をつけてもよいならタグディスパッチ
だめならlokiのTypeTraitsで使えそうな特性をみつけるとか。
私的には特定のクラスのサブクラスかどうかで分けるのが良いと思うが。
>>613 なんだかよく分からないのですが、
>>583 氏のヘッダに適宜 LokiPortのコードを移植することで、
LokiPortのTest_Typelist.cpp がコンパイルできてしまいました。
ということは、Typelistに関してはVC6でも動作可能ということですよね。
ううむ。
移植完了品をパッチかアーカイブの形式で全部UPしてください
>>636 VC6ってテンプレートパラーメータサポートしてなかったと思うけど
どうやってるの?
>>638 ん? できないのは部分特殊化でしょ?
テンプレートパラメータサポートしてないってどういうこと?
文字通り取るとtemplate自体使えないような。
>>639 テンプレートテンプレートパラメータのことでしょ。わざわざ揚げ足取らんでも。
template< class A, template<class> B > class C { ... };
ってゆーかしかし、LokiのTypeListって部分特殊化さえあれば動くと思ったが。
LokiPortのTypeTraits::isConstがうまく動かない・・ 参照型が問答無用でconstと判断されてしまう。 まぁあんまり使い道の無い機能ではあるが ザンネン。
・・・よくよく考えると 参照そのものは変更できないからconstという判断でいいのかな。 そういうことにしよう!
ん? isPointerの実装おかしいような?? これconstの判別できないだろ?
>>646 そうなんだよね・・
それなのになんで動くのかちと不思議。
保障されない動作なんだろうか。
とりあえずisPointerはポイント先の修飾された奴を全部消して
コンストポインタの判定を追加したらうまく動いた。
template<typename U> static yes is_pointer1(Type2Type<U *>); static no is_pointer1(...); template<typename U> static yes is_pointer2(Type2Type<U * const>); static no is_pointer2(...); enum { isPointer = sizeof(is_pointer1(Type2Type<T>())) == sizeof(yes) || sizeof(is_pointer2(Type2Type<T>())) == sizeof(yes) || }; これで動いた。 これって単に動作確認してなかったのかな。 それともSPあてる・あてないで動作変わったのかな・・
649 :
デフォルトの名無しさん :02/06/16 11:18
>>632 激しく遅レスだが
VC++には__if_exists/__if_not_existsなるキーワードがあって
関数や変数の有無で処理を分けられる
移植性を考えれば使えないが
>>650 #include <iostream>
int main(void)
{
int a;
__if_exists( a ){ std::cout << "a ハケーン" << std::endl; }
__if_not_exists( a ){ std::cout << "そんな変数無いです" << std::endl; }
}
こんな感じ
このままだと "a ハケーン" が表示される
int a;をコメントアウトすると "そんな変数無いです" が表示される
( ) 括弧の中は変数だけじゃなくて、任意のシンボルが入れられる。
もちろんメンバ関数も。
>>651 ネイティブにも使えるけど、もしかしたらVC++.NETから新しく追加された機能かも
6.0には無かった。
655 :
名無しさん :02/06/16 19:11
このスレに巣食ってる型はハイレベルですね・・・。
こういうのぜひ 規格 にフィードバックして欲しい (識別子をどうするかは、考えないといけないが)
>>657 コンパイラによるリフレクション? 規格はさすがに無理ぽそうだけど...
659 :
名無しさん :02/06/17 02:06
std::advanceのようなアルゴリズムを記述するのに、 タグディスパッチがいらなくなるんじゃない
661 :
名無しさん :02/06/17 08:21
template <class _Iterator, class _Distance> inline void advance(_Iterator& __i, _Distance __n) { __if_exists( _Iterator::operator[]){ __i += __n; } // random __if_exists( _Iterator::operator--){ if (__n >= 0) while (__n--) ++__i; else while (__n++) --__i; } // bi // elseがないからtag抜きでforward iterator書きにくい。 } こんな感じ?
Templateを初心者にも分かりやすく教えてください。
>>662 コンパイラがコンパイルの前に置換をしてくれるんだよ。
プリプロセッサがやる単純な置換と違い、コンパイラが型チェックに
責任を持ってくれる。
>>633 Templateはどういうときに使うのですか?
>>664 リストって知ってるよね?単方向でも双方向でも。
例えば、構造体Aと言う値を保持するリストのクラスを作ったとする。
これがなかなか便利で他のプログラムにも使いたい。
しかし、構造体Aは前のプログラム独自の物なので汎用性を持たせたい。
そこで、構造体Aの代わりにvoid *を持たせることにした。
しかし、これでは型キャストの嵐になるし、新しいノードを作るとき、自動的にデータ格納用の
メモリ領域を確保したり開放したりすることが困難になる。
next = new nextnode();
next.data = new ここを使う型が変わるたびに変更しなくてはならない。
そこでテンプレート。これは特定の抽象型を具体的な型に置換できる。
例えば、データ用の型をDATAとし、それをintと具体化すれば、
int型を扱うリストが出来るし、struct aaaと具体化すればaaa構造体のリストとなる。
あれ、完全に置換はしないってあったような気がするけど
667 :
デフォルトの名無しさん :02/06/17 23:10
>>664 抽象化する時
(メソッドとか関数とか)
>>663 >>665 激しくスレ違いに真面目にレス。2ちゃんねらーの鑑です。
私も見習わないと。
ということで真面目レスを追加しておきますと、
テンプレート(template)の萌芽はMFCのコンテナにも見られます。
(CMap、CListなど)
でもやはり、STLは一通り勉強しましょう。
ttp://www.wakhok.ac.jp/~sumi/stl/index.html それから、Effective C++、More Effective C++を一通り読んで、
>>1 のModern C++ Design を買えば、
晴れてこのスレの住人に仲間入りです。
頑張りなされ。
669 :
デフォルトの名無しさん :02/06/18 21:12
Effective C++、More Effective C++、Modern C++ Design いくらかかると思ってんのYO(`Д´)
>>669 全部持ってるYO!高かったけど仕方ないYO!
>>669 書籍にかけた金は、すぐに仕事実績で取り返せる(ちゃんと読めば)。惜しむな。
> 書籍にかけた金は、すぐに仕事実績で取り返せる(ちゃんと読めば)。惜しむな。 そう思いこみたいんですね :)
「primitiveな変数をいちいちconstructorで 初期化するのはめんどくせー」ってことで、 WithInit< int , 600 > m_intvalue; ちゅーよーなのを書いた。 ひょっとして、車輪を再発名した……?
>>674 勝手に600に初期化されるint ってこと?
VC++.NETにて下記のコードで InnerInStrict がコンパイルエラー "error C2516: 'Inner' : は正しい基本クラスではありません。" を吐きます。 InnerInFunc は問題なく通ります。 これはC++の仕様?それともVC++の問題? InnerInStruct も使えるように出来ないのでしょうか? struct Base{ struct Inner{};}; template< typename T > struct Mid: public T{}; template< typename T > struct Sub { struct InnerInStruct: public Mid< T >::Inner{}; Sub() { struct InnerInFunc: public Mid< T >::Inner{}; } }; int main(void) { Sub< Base > sub; }
>>676 g++3.1やbcc5.5.1では何ごともなく通ったよん
>677 bool, int ,char , short, long , float, doubleと使えれば 充分じゃねーんすか?
Genericプログラミングマニアのみなさま。汎用シーケンスコンテナを作れませんか。 Effective STLの第2項、「コンテナに依存しないコードという幻想に注意しよう」を 読んだ上で言ってます。 vector,deque,listってのは、しょせん実装の詳細なわけですから、最初っから 「汎用シーケンスコンテナ」ってのがあって、その実装を、vector,deque,listなどの中から ポリシーで選べたら便利なんじゃないかと思うわけですが。 Effective STLには、たとえば「vectorをサポートしようとすると、push_frontとpop_frontを 使用できない」とか書いてあります。要するに、「全部に共通するメンバ関数がないから、無理」 ってなことに過ぎないわけでして。全部ラップして作り直せば問題解決なんでは、と思った わけです。どうでしょう? // ポリシークラスその1。vectorによる実装。 template<class T> class ImplVector { public: typedef std::vector<T> cont_t; typedef cont_t::iterator Iter; typedef cont_t::size_type SizeType; private: cont_t c_; public: void PushFront(T val){ c_.insert(c_.begin(),T); } void PushBack(T val){ c_.push_back(T); } void Erase(T val){ // eraseとremoveの慣用的用法ってやつ。 c_.erase(remove(c_.begin(),c_.end(),val),c_.end()); } T& operator[](SizeType n){ return c_[n]; } };
// ポリシークラスその2。listによる実装。 template<class T> class ImplList { public: typedef std::list<T> cont_t; typedef cont_t::iterator Iter; typedef cont_t::size_type SizeType; private: cont_t c_; public: void PushFront(T val){ c_.push_front(T); } void PushBack(T val){ c_.push_back(T); } void Erase(T val){ c_.remove(T); } T& operator[](SizeType n){ Iter it = c_.begin(); for (int i=0;i<n;++i){ ++it; } return *it; } } // Generic Sequence Container template < class T, template <class> class ImplContainer = ImplVector > class GSC : public ImplContainer<T> { }; GSC<int> gsc; gsc.PushBack(3); gsc.PushFront(5); gsc.Erase(3); int a = gsc[0]; こんな感じで、効率の良し悪しは無視して、思いつく限りのメンバ関数を 用意しておけばいいんじゃないかなと。後で「vector実装でOKだと思ってたけど、 list実装の方がよかったな〜」ってときは、GSC<int>って定義をGSC<int,ImplList>に 変えるだけです。使ってる部分のコードは全く変更しなくていい、ってのが当然の目標。 ……とかいって、どっかですでに開発されてましたー、じゃ虚しいんで、 存在を知ってる人がいたら、さっさとツッコミ入れてくださいね。
>>674 初期値を変更したくなったときに依存してるソース全部で
再婚パイルが必要なのって面倒い。
>>682 「vectorでOKだと思って operator[] を使って色々実装していたけど
やっぱりlistの方が良かったなー」なんてことは起こり得んと思うがどうか。
例えば std::queue のコンテナにはほとんどの実装だと list/deque は取れても
vectorは使えないけれど、それはvectorを使う意味が全くないからであって、
そこにあえてvectorを渡せるように汎用性を持たせる…みたいなことって
やってもしょうがないのでは。
>>680 > bool, int ,char , short, long , float, doubleと使えれば
> 充分じゃねーんすか?
いや、template に float や double (char もか?) の即値はつっこめないのではないかと。。。
>>683 いや、それは単にそういうありえなさそうな状況を挙げてるだけでは。(^^;
operator[]を使うって事は最初っからlistが考慮の外なのは明らかですから、
そういう状況を持ってきて否定されても。std::queueのほうも、目的が
はっきりしているなら、汎用シーケンスコンテナなんて必要ないのは
あたりまえです。
とりあえず、俺がこれを欲しいと思った動機を。vectorでもlistでもいいような、
曖昧な状況で『とりあえずvector』で開発をはじめたけど、あとで『げ、中間への
データ挿入が出てきた。やっぱlist』って切り替えたくなったんです。そのとき、
データ削除部分の形がvectorとlistでは全然違うやん、ってので参ったんです。
要するに、『どのシーケンスコンテナが最適なのか、不透明な状況』に対して
最適な回答をもたらすために、汎用シーケンスコンテナがあればいいなぁ、と。
どのコンテナが最適なのかわかんないうちから開発を始めてんじゃねーぞ、
って言われたら、「はい、ごめんなさい」と凹むしかないですが……。
Effective STLに書いてあったかどうかしらんが、必ずtypedefをするようにしとくだけで いいんでないの? いちおう、 どういうコンテナを使うべきかの分析無しで作りはじめてんじゃねーゾ。
687 :
デフォルトの名無しさん :02/06/19 23:31
age
>>685 私の場合は、テキストエディタを作るときに1行のテキストを
stringに入れて、listに入れて使いました。
stringはコピーにコストがかかるので、
vector::[] + insert よりは、
list::advance + insert の方がパフォーマンスがよかったです。
(advance 10万回で0.04秒程度)
しかしそれはコンテナの性質と設計上の要請を勘案すれば
事前に分かることで、わざわざポリシーにするほどのことではないと思うのですが。
テキストエディタはlist+キャッシュと言うのが常套手段だよな。 もう常識中の常識。 それより、1行に持てるデータの構造をどう記述するかの方が問題。
>>686 typedefは必ずやってます。
>>681 で書いてるみたいなやつを。
でも、typedefじゃ『削除』はどうにもならないんですよね。
とりあえず逝ってきます……。
listっておい、まともなやつはgapped bufferだろ..
>>691 listとギャップバッファは用途違うと思うが?
それから、ギャップバッファも1行に保持するデータが長くなってくると
パフォーマンスががた落ちするよ、所詮2セグメントのデータだからね。
>684 VC++6で、double即値、char即値ともつっこめますた。
Boostにごっついtype_traitsの実装があることに今ごろ気付きますた・・・!! 死のう。
>>691 は何行になるかわからんのにいちいち行ごとに
オブジェクト作るなって言いたいんじゃないのか?
そういう点でみれば
>>692 のは激しく的はずれ
gapped bufferってn行へジャンプとかが苦手じゃないの?
苦手といえば苦手だが克服は簡単だよ 最近のPCは速いし。
listと違ってn行へのジャンプが定数時間で終わるのがgapbufferじゃないのか?
>>698 gapped buffer って、バッファの内容をカーソル位置で分割して管理する方法だよね。
それだと、コストはこうじゃないかな。
gapped buffer
一文字追加、削除 O(1)
指定行の移動 O(バッファの総文字数)
リスト
一文字追加、削除 O(一行の文字数)
指定行への移動 O(ファイルの行数)
gapped buffer は「普段よく使うのは一文字単位の追加・削除だから、こっちを
早くしたほうが快適だ」という信念に基づくデータ構造だと思うよ。ついでに、今
時の PC を前提とするなら、どっちでも早すぎて変わらん。
>gapped buffer って、バッファの内容をカーソル位置で分割して管理する方法だよね。 これだと先頭から終端までジャンプするのに、バッファのコピーが発生するよね? めちゃくちゃ遅くならない?
>>700 挿入・削除のタイミングでバッファ内の整理をすればよいので
全然そんなことない。
極端にでかいファイルもストレスなく開けるようにするのに便利。
VZは行編集バッファを別に持って、 何か書き換え始めたら行編集バッファにコピーしてきて編集し、 カーソルがその行から出たりするタイミングで書き戻してたっけ。
703 :
デフォルトの名無しさん :02/06/22 03:10
ちょっと質問 gapped bufferってデータを head part cursor tail part |-----------| + |------------| こんな感じで持つ構造と考えて良いのでしょうか? それとも、下の様にいくつかのフラグメントに分けて保存して、 編集時のコピー量を少なく納める構造なのでしょうか? |-----| |-----| |----+-| |------| 日本語のサイトをいくつか検索しても、 どっちとも取れるようなどっちも違うような記述でよく分かりません
704 :
名無しさん :02/06/22 03:16
後者は変形の一つ。
>>700 正直、editorならほとんど変りがない。今や一番重いのはGUIの描画。
>>703 カーソル位置とギャップ位置は関係ない
ギャップは普通エディットしている部分に作られる
どうでもいいけど話題がスレ違い
ではだれかgapped bufferをgenericに実装した例をキボンヌ
gapped bufferのメリットがぜんぜんわからぬ・・・
711 :
デフォルトの名無しさん :02/06/23 12:31
STLPortとLokiPort(のSmallObj)同時に使えないっすね。 STLPortのlower_boundに不具合があるんですけど、 どうにもならないですかね。
>>711 lower_boundにどんな不具合がありますか?
>>712 ぉ!
Generic Programing and the STL見てみたら、
STLPortの動作のほうが正しいですね。
// MSDNには書いてない新たな条件が・・・
LokiPortのほうの使い方に問題があるみたいですね
boostのTypeTraitsのコード読んでたんだが ちょっと前、Lokiの移植で話題になってたVCで テンプレートの部分的な特殊化をエミュレーションしてる部分に こんなコメントかいてあるんだけどあれのどこが not legal なの? ーー以下引用ーーー // the following VC6 specific implementation is *NOT* legal // C++, but has the advantage that it works for incomplete template<class T1> struct is_same_part_1 { template<class T2> struct part_2 { enum { value = false }; }; template<> struct part_2<T1> { enum { value = true }; }; }; ーー引用ココまでーー 他のコンパイラでは動かないのかな?
715 :
デフォルトの名無しさん :02/06/24 02:26
.NET Framework SDKについてるC++のコマンドラインコンパイラでは Lokiを使えますか?
>>716 過去ログにはVC++.NETとあるだけなので、VisualStudioなのか
.NET Framework SDKだけでも大丈夫なのかわかりませんが。
>>717 一応、最適化のオプションが使えなくなってるだけで、
あとは普通にManagedも吐ければ、通常コンパイルもできる
まずは使ってから質問しろ。
lokiが使いたいだけならgccにしろ。
>>718 使うかどうかまだ決めてないんで。
情報どうも。
VC7.0のコンパイラって何処で落とせますか??
723 :
デフォルトの名無しさん :02/06/26 10:36
VC7.0はtypeof演算子は使える? g++だといけるんだけど。
>>723 それがGeneric Programmingと何の以下略
>>724 コンパイラへのプログラミングにおいて
限られた道具が増えることは、かなり重要なことだと思うけど・・・
今のところ、どう使うか考えてるところではあるんだけどね:)
処理系依存の話は、できれば余所でお願いしたいところだが。 (まぁ C++ の template 自体、完全実装してる処理系はほとんどないから、 処理系依存に近いのが現状だけどさ)
あ、凄いのはtypedef templateの方ね(笑
どっちもホスィ・・・
typeofって拡張だろ?
>>730 標準に含めて欲しいっていう提案はされてるみたい
なるほど、スレ違いってうまい言葉だなあ
733 :
標準化委員会 :02/06/27 00:38
typeofはもうすぐ導入予定です
typeofはいいから早くANSIに対応してくれよ>VC++ g++ってあれだけがんばってるのに、ユーザーは 相変わらずCでゴリゴリ書くのが好きな人ばっかりで、 なんか哀れだよね。
typeof萌え、標準にすぐ入れるべし、
typeofはテンプレートのないCに取り入れられた方が 劇的にコーディングスタイルが変わりそう。
>>736 マクロプログラミングですか?
イヤだなぁ
#define foreach( itr, cont ) for( typeof( (cont).begin() ) itr = (cont).begin(); itr!=(cont).end(); ++itr )
739 :
デフォルトの名無しさん :02/06/28 04:25
template<typename T>struct SA{ template<typename A,typename B>struct TSA{TSA(){cout<<"A"<<endl;}}; template<>struct TSA<T,int>{TSA<T,int>(){cout<<"B"<<endl;}}; template<>struct TSA<T,double>{TSA(){cout<<"C"<<endl;}};←これが警告になって、しかも無視されるのがわからない。なんで? };
オーバーロードの曖昧さ?
741 :
デフォルトの名無しさん :02/06/29 18:05
Cスタイルの文字列を受け取れるテンプレートで、 const char* を受け取れるようにしとけば動作するけど、 template< unsigned N > f( const char (&x)[N] ); にバージョンを用意しとけば、文字列リテラルを受け取ったときに、 N で文字列長を受け取れる分、より効率的に処理できるようです。 ですが、↑みたいなテンプレートを使ってるのをほかで見たことがありません。 なにか問題があるからなのでしょうか? それとも、見つけれて無いだけで、めずらしくもない方法なんでしょうか?
>>741 boos::type_traits::is_array
^boos^boost
>>742 配列型の判別はできても、boostのやつには N が取れないように見えますが、
同じことができるってことですか?
LokiPortのis_arrayにも似たような記述があるが 環境依存な部分も少なからずあるみたい。 ただ単にサイズを自動的に取得したいという目的ならば不要かと。 const char* との共存ができないようだし。(VC7) 普通にstring(literal, sizeof(literal))で問題無いかと。
もうtemplateは疲れた。
正直、Lokiの延長みたいのが仕事で使われるようになったら、 この業界辞める。もっとらくちんなの希望。
748 :
デフォルトの名無しさん :02/06/30 02:51
>>747 ライブラリ作るのとそれ使うのとでは全然違うと思われ
749 :
デフォルトの名無しさん :02/06/30 15:43
>>747 激しく同意。
STLのように使うだけのライブラリとはちょっと違う。
プログラム設計において根本から変わってしまうような
ものだと思う。
というかそろそろ言語の機能をフル活用しなければならない
っていう呪縛から逃れたいところだね。C++使ってるひとには
自分も含めて、この傾向が強いから。
自分が便利だと思う機能をしっかりと使えればいーんじゃネーノ? ……と思ったが、そうすると他人のプログラムの保守ができんな。
機能は、必要を感じた時に初めてその使用の検討をするべき。 templateなんて特にそうだと思うぞ。 俺は無いと困るみたいな状況に陥ったことがないので、 使ったことは無いが。w
>>751 > 機能は、必要を感じた時に初めてその使用の検討をするべき。
とはいえ、全く知らないと
これを使えば簡単に済むのに
っつーことに気づかぬ罠。
templateで一番威力を発揮するのはコンテナでしょ。 その辺だけ使えればいいんじゃないの? 構文汚いけど。
関数オブジェクトもなかなか
755 :
デフォルトの名無しさん :02/07/01 09:06
GenScatterHierarchyとGenLinearHierarchy最高。 さてこれをどう使ったらいいものやら。。
>>755 クラスのメモリレイアウトをコントロールできない。
というわけでスクリプトでプログラムを書くときのように
手軽に、巨大なシステムを構築してしまいたいが型は
大切にしたいとき(どんなときだ?)に使う。
757 :
名無しさん :02/07/01 11:40
>>749 「プログラム設計において根本から変わってしまう」ことと、
「言語の機能をフル活用しなければならない」は相関性弱いと思うが…
後者は実装の話でしょ。
俺はcompilerのerror messageさえなんとかなれば、Lokiくらいは容認。
プライベートなコーディングにおいては Loki使いまくり。正直、もう昔のGoF本に載ってる ような野暮ったいコーディングには戻れない。 Typelistは最初は違和感あるけど、我慢して一ヶ月ぐらい 使いつづければ誰でも慣れる。typelistの新たな 使い方を考えるのはかなり厳しいが、MCDの 本に載ってるようなDPへの適用を真似る程度であれば 大したことはない。
MCDってなに?
ModernC++Designのことね。勝手に省略ゴメソ
761 :
デフォルトの名無しさん :02/07/01 17:33
「ふーん、そんなこと言える身分なの?」 「恥ずかしいことしてるのばれちゃってるのに・・」 3人はイチゴの顔をじっくりみつめる。 そしてその中の1人がそっと言った。 「しかたないわ、あ私たちめくるのやめるわ。」 イチゴはほっとした。 『許してくれるんだ・・・・』 「ありがとうございます・・・・」
型のコレクションをマクロ無しで扱う機能を次のC++標準に入れて欲しい。
>>763 現在の ANSI C++ 決めるまでにかかった時間から考えて、次の ANSI C++ 規格
が出るのは
話し合いが始まる 2005年
リリース目標 2008年
実際に決まる 2010年
ぐらい?
コンパイラベンダの実装完了目標 2015年 実際に実装される 前に次の標準の話し合いが始まる 無限ループ?
つーか今の規格でもういいよ。 SQL99みたいになっても意味無し男
>>765 VC++はそのころになっても現在の規格にすら準拠できてなさそうだな・・・(鬱
768 :
デフォルトの名無しさん :02/07/02 07:55
LokiからBasicFastDispatcherってどうして取り除かれたの? 致命的なバグでも見つかったとか? 一番実用的なアイディアだと思っただけに残念。。
ポストC++を開発する良い機会だと思うけど。
>>770 あと7年・・・それまでにパソコン業界はどうなっているのだろうか?
ハードディスク1TB超、CPU10GHz、メモリ10GBなんてのは当たり前に
なってそうだ。いや、これくらいなら4年もあれば実現する。
(C++)++ってのは文法違反か?
CPU4台くらい積むのが当たり前になってるかもね。 基本は省電力モードで休眠状態。 いわゆる論理区画みたいなもんかね。 そうなっているとすれば、そのころのOSの役割は 本来の資源管理にのみ特化しててもよさそうだね。
> (C++)++ってのは文法違反か?
Cの型(というか多重定義演算子の定義のされ方)による。
>>771
10年後はC++の次ができてそうだね
>>773 なるほど。基本型はエラーになるようだ。
>>774 Cを拡張したのがC++だけど、もうこれ以上小手先だけで拡張できない
ほどメチャクチャになっているので、新しい言語を作った方がいいような
気がする。
CPUで言うと丁度x86みたいな様相を呈しているからな・・・・・
とりあえずC互換部分を(全部とはいわないけど)なるべく消して欲しい。 "..."とかも。(そうなるとModern C++ Designが困るのだが) あとグローバル変数も要らん。
>>776 C++ - C ってことは、言語名は ++ ですか?
>>775 確かに template がらみだと、
「たしかに template 使えばできるけど、あまりに直感的じゃない。言語の方で
直にサポートしてくれよ」
という機能も多いよな。でも template がこんなに強力な代物だとは、出てきた
当時は思いもよらなかったよ。
クラスつきのCとしてのC++からC互換の危ない部分を取り除いて それをベースに型推論を導入してテンプレート宣言はやめる。 代わりに仕様として部分評価を導入して生成的プログラミングスタイルをサポート。 (つまり関数はデフォルトで暗黙のうちにテンプレート関数なわけ。値による特化は部分評価技術で。) ただクラス・テンプレートの宣言をどうするかはちょっと迷うところだ。 関数型言語のように構築子を強化してクラス宣言を特殊な関数宣言とみなして 構造体アクセスのパターンマッチング機能と組み合わせてと言う路もあるが、 あまりにもCらしさからかけ離れてしまう気がするし。 (命令型C風MLみたいになってしまう。)
780 :
デフォルトの名無しさん :02/07/03 19:48
静的型付け言語の現状C++マンセー!!!
>>780 型推論は、強い型付けと矛盾しないけど。
>>781 あ、そなの?MLとか知らないからよく分からんけど。。
その辺は他の言語もやってみないとダメだね。
783 :
デフォルトの名無しさん :02/07/03 20:00
Cの怨念部分を取り払う時期がくるか
ちなみにAlexandrescuはMLやHaskellなどの関数型言語も、 自著で名前を何回も出すぐらいだからかなり知ってるのかもね。
つーか、プログラミング言語ネタで本を出すようなヤシでML知らないのはモグリ。
MLやHaskellにいかずとも、空リストや特殊定義でlispを思い出 す以前に、リストにアルゴリズムを施したりファンクタ つくらせてカリーイングやったりという近年のC++の傾向そのもの がオブジェクト指向と別方向の関数型言語指向なわけで。 lispと違って、それなりのパフォーマンスを維持しつつそういう 遊びがあるところに近時のC++の長所があると。 ただ実用から行くと、Java + generics + メモリ直接操作 くらいが 受けのいいところでしょ。 どうせ次期標準C++なんていってもせいぜい確率高い順に hash_map他のSGI拡張、boost等のスマートポインタ、正規表現、数学等のライブラリが入るかどうか サイズ規定のプリミティブ型が入るかどうか typeofやらclosure/delegateやらの言語拡張が入るかどうか マルチスレッドやネットワークのサポートが入るかどうか とかだろ? しかも付け加えてばかりでは実装上文句が出るはず だけど具体的にどこってのは全然見えない。そもそもVC++8のリリ ース時期に合わせないと誰も使わないだろうな。 C99と互換性無いと駄目とかそっちの方がむしろ主流ではないの。
>>786 同じ文章をどこかで見たことがある気がする(デ・ジャ・ヴ?)
長所禿同
C++には多少手を加えるにしても全体としては今のままを維持してホスィ・・・
OOPらしいOOPがやりたい人はJavaでもC#でもやってりゃいいんで
性能と手軽さのトレードオフのある今のOO/GenericなC++でだいたい足りるわ。 今ある規格には準拠して欲しいとも思うがね。 それよりコンパイラのバグ減らせ!
789 :
デフォルトの名無しさん :02/07/05 06:42
gcc3.1+boost1.23でlambdaを使ってます。 下の結果が3ではなく、4になってしまうのですが、 どうしてでしょうか? int i = 1; std::cout << (_1 + i)(i = 2) << std::endl;
_1 って? それにスレ違い
>>790 別にスレ違いじゃないだろ。genericsがらみだし。
>>789 boost 1.23??
>>789 一つ言えることは _1 + i と i = 2 のどちらが先に実行されるかわからないのだから
そういう書き方をしてはダメってことだ
>>791 あ、1.28です。
最新版の配布パッケージです。
boost::lambdaのドキュメントには
>int i = 1;
>(_1 + i)(i = 2);
>The value of the expression in the last line is 3, not 4. In other words, the lambda expression _1 + i creates a lambda function lambda x.x+1 rather than lambda x.x+i.
このように書いてあるのですが…
795 :
デフォルトの名無しさん :02/07/05 12:34
未定義じゃないはず。 ((int(*)(int))operator+(_1, i))(i = 2); たしか、こんな感じになるはずだし。
_1 そっか、各種名前としては成立するな・・・。クソ迷惑だけど。
普通にx/y/z等を占有されるよりも_1/_2/_3の方がいいじゃん
798 :
デフォルトの名無しさん :02/07/05 14:01
>>798 残念ながら使いこなすほど成熟したライブラリではないと思う。
Alexandrescu本人も実際に使ってるかはなはだ疑問。
ACEはLoki的な書き方をすればコードはかなり小さくなりそうな予感。 完成したライブラリではないが、それてきなものをテクニックの一つと 捉えて、どんどんコードを書いていくことは大事なことな気がする。
801 :
名無しさん@Emacs :02/07/15 00:35
お前らちゃっとTypelist使ってますか?
ちゃっと使ってます
>>802 どうつかってるの?
本にのってるやつ真似てるだけ?
それとも自分で新たに技作ってやってるとか?
804 :
デフォルトの名無しさん :02/07/15 04:02
>>803 意味解析すると
>>801 による、
>お前らちゃっとTypelist使ってますか?
という誤文(正しくは「ちゃんと」であろう)に対して、
>>802 は同じ調子で、
>ちゃっと使ってます
と応答した。
これは恐らく「ちゃんと」と「チャット(chat)」を掛けている可能性が高い。
よって、
>>802 が本当に「ちゃんとTypelistを使いこなせているよ」
という意味で返答したのかどうかは、このレスでは判断できない。
また、これを踏まえると
>>802 に対しての
>>803 の応答は、
抽象的すぎるきらいがある。
>>802 への適切な応答としては、
1)s/ちゃっと/ちゃんと/
などとし、話の流れを元に戻すか、
2)チャットは何のソフト使ってるの?
が考えられる。
Typelistはべつに新たに使い方を発明する必要はないな。 そういうのは一部の天才たちに任せよう:) それよりもデザインパターンを適用したソフトウェア設計が できるかどうかの方がよっぽど大切。これが出来ないことには Alexandrescuの本に書いてあることの多くが使えない。 おれはよく知らないけど、Typelist自体についてもっと 勉強するには他の型付関数型言語のコーディングテクニックとかを 勉強する方がよいんじゃないの?
>>801-804 名古屋弁で「ちゃっと」といえば「さっと(すばやく)」くらいの意味だ。
ちゃっとやっとかんとかんわ。=さっとやっておかななければならない
Effective C++読み終えたよ。 大体は知ってたけどいろいろと役に立った。 次はMore Effectiveでも読むかな。
>>807 Moreは訳がくそなので読むのに想像力と忍耐力が必要だぞ。
(ここでいうことでもないのでsage)
頭の中で英語に訳しながら理解すべし。(ワラ
bk1 で More 注文したけど入荷できずにキャンセルされちゃったよ。 思い切って洋書を注文したよ。がんがろ。
More Modern C++ Design
effective C++って第2版でどう変わったの?
D&E ARM (;´Д`)
>>812 標準C++の文法に準拠した新しい機能を使っている。
救いage
>>813 すごいな、漏れは "コンストラクター" と、伸びる時点でかなりひいたし、
後半はわけがわからないので、原書かっちまったが・・・
>>817 伸ばし棒の事なんかどうでもいいから後半のわけわからないっぷりについて
おしえてください。
>>819 たとえば、
const と コンストラクタ が混同されている部分があったりする。
そんな間違いをできるくらいで(だって普通文脈上そんな間違いできないでしょ)、
訳者は著者の書いていることを全然理解してない。
その点ModernC++Designの村上氏は、 誤植の問題にも逐一訂正を載せてるし、 原著の修正にも載ってないものに 関しては報告してるみたいだから素晴らしいね。 翻訳もののダメっぷりばかりが目立つ この業界の出版事情だけどいい仕事してる ひともいるわけで、そういった人の本が もっと売れるようになって欲しいところだね。 ダメな人を晒あげても切りがないので、 いい仕事をしている人を取り上げよう。 私は村上さんの本は信頼できると思います。
そういや訳してるヤシはプログラマなのか?
関数ポインタを勉強してるんですが、 CTest2みたいなことは無理でしょうか?(CTest1はOKでした) /* int test(int a) { CTemp temp; return temp.Func(*this,f,a); } クラス(*this)を渡して動的にテンプレートで作成させれば 何個も CTemp<???> を作らなくて済む。 */ #include<iostream> using namespace std; template <typename _T>class CTemp {public: typedef int (_T::*Pstd)(int); int Func(_T& ob,Pstd f1,int a) { return (ob.*f1)(a); } }; class CTest {public: int f(int a){ return a*2;} int test(int a) { CTemp<CTest> temp; return temp.Func(*this,f,a); } };
class CTemp2 {public: template <typename T,typename R> typedef R (T::*Pstd)(R);//typedef はtemplate化 できないのか? template <typename T,typename R> R Func(T& ob,Pstd f1,R a) { return (ob.*f1)(a); } }; class CTest2 {public: template <typename TM1>TM1 f(TM1 a){return a*2} template <typename TM> TM test(TM a) { CTemp2 temp; return temp.Func(*this,f,a); } }; int main() { CTest t; cout << t.test(100); CTest2 t2; cout << t2.test(100); }
>>826 typedef のテンプレートはまだできないよ
>>827 そうでしたか...。ちょっと変えたらできました。
class CTemp2
{
public:
template<typename T,typename R> R Func(T& ob,int (T::*f1)(R),R a)
{
return (ob.*f1)(a);
}
};
class CTest2
{
public:
int f(int a){ return a*2;}
template<typename R> R test(R a)
{
CTemp2 temp;
return temp.Func(*this,f,a);
}
};
下みたいにすると、 関数テンプレートを関数の引数として使用できません。 とでるんですけど、 無理なんでしょうか? (補足:828はC++.NETならコンパイル可です。gccはオプションの設定が よく分からないのでコンパイルできませんでした) class CTest2 { public: template<typename R> R f(R a){ return a*2;}//ここを変更 template<typename R> R test(R a) { CTemp2 temp; return temp.Func(*this,f,a); } };
>>830 少なくともVC++.NETならこれで通った。
template<typename R> R test(R a)
{
int (CTest2::*tf)(R) = f<R>;
CTemp2 temp;
return temp.Func(*this,tf,a);
}
が、bccとかgcc2.95はICEる。gcc3.xはわからん。
832 :
デフォルトの名無しさん :02/07/25 12:51
>>831 できた!サンクス。
LokiのFunctorをVC++.NETでコンパイルできないんだけど
やっぱり書き換えないと駄目なのかな?それとも設定ミス?
template<typename R> R test(R a)
{
typename R (CTest2::*tf)(R) = f<R>;
CTemp2 temp;
return temp.Func(*this,tf,a);
}
++a+a+++a+++a+a+++a+++a+a+++a+a+++a++; // + 激しくインクリメント + //
ジェネリックネタは尽きたか・・・!?アゲ
837 :
デフォルトの名無しさん :02/08/12 02:13
template<class T,class S>class Typelist{ typedef T t; typedef S s; };
>>837 パブリックのメンバしかないクラスはstructを使うのが
彼のコーディング規約らしい。
あとテンプレートパラメータがプリミティブになるときにはtypename
これが一番役にたったかな。。。鬱
839 :
デフォルトの名無しさん :02/08/13 08:40
template<class T,class S>struct Typelist{ typedef T HEAD; typedef S TAIL; }; template<class A>struct TCA{ typedef A::HEAD A; typedef A::TAIL B; A a; }; void main(void) { TCA<Typelist<int,double> > tca; } なんでエラーになるねん?
間違ってるから
>>838 > typedef A::HEAD A;
そりゃー無理だろう。
template<class T,class S>struct Typelist{ typedef T HEAD; typedef S TAIL; }; template<class A>struct TCA{ typedef typename A::HEAD HEAD; typedef typename A::TAIL TAIL; A a; }; void main(void) { TCA<Typelist<int,double> >::HEAD tca1; TCA<Typelist<int,double> >::TAIL tca2; }
Lokiにはstruc.incの亡霊が見える。 こういう拡張は、言語の死の前兆なのだろうか、と思ってみたり。
845 :
デフォルトの名無しさん :02/08/18 04:05
著者はテンプレの制限追っかけるより 手っ取り早くcppを拡張してほしい。 C++は詰め込みすぎだ。
846 :
デフォルトの名無しさん :02/08/18 22:02
多次元配列についてはどうだ?
なにが?
最近boost-mlではMPLの話題が多いのぅ… あれがboost本家に入ればここも盛り上がる…かな?
849 :
デフォルトの名無しさん :02/08/21 23:57
誰か俺に力を template< typename T > class A { public: //A(void){} ~A(void){ T::function_not_called(); } }; class B { public: A< class C > c; }; int main(void) { new B(); } VC.NET A()のコメントはずすと~A()でコンパイルエラー・・・Why?
>>849 g++ でちょっと調べてみた。
A() がある場合、 B() をコンパイラが生成する。
で、 B() が生成された段階で、 B(){throw 0;} みたいなコードに
対応するために(だと思う) ~A<C>() がインスタンス化される。
A() が無い場合、 B() も無いことになって、このとき ~A<C>() はインスタンス化されない。
ためしに、 A(){} をコメントアウトしたまま、 B(){} を追加しても同じエラーになる。
でも、 B(); として外部参照にすると、エラーは消える。
これは、 ~A<C> が B() のコンパイル時にインスタンス化されているということだと思う。
それならと思って例外処理を無効にするオプションを追加してみたけど、
結果が変わらなかったのがよくわからないところ。
>>850 あんたすごいよ!
俺は思いつきもしなかった・・・
VC.NET も同様の結果。
実際のコードは B もテンプレートだったりして、あきらめるしかないか。
852 :
デフォルトの名無しさん :02/08/23 18:17
プチStateパターン。なんてのを提案してみます。 状態ごとに振る舞いを変えたいけど、Stateパターンをやるまでもないという 場合は、だいたいこんな感じでやってますよね? // Hoge.h class CHoge { int state_; void age(void) {} void sage(void) {} void giko(void) {} void mona(void) {} public: void Action(void); }; // Hoge.cpp typedef void (CHoge::*FUNC)(); FUNC table[] = { &CHoge::age, &CHoge::sage, &CHoge::giko, &CHoge::mona, } void CHoge::Action(void) { // 状態ごとに振る舞いを変える。 (this->*table[state_])(); } こうやっていると、ひとつ状態が増えただけで、呼び出す関数が増えるから、 Hoge.hを書き換えなきゃならないのが弱点。そこで、こんなのはどうでしょう。
853 :
デフォルトの名無しさん :02/08/23 18:17
(続き)
// Hoge.h
class CHoge
{
int state_;
template<int> void InnerAction(void);
public:
void Action(void);
};
// Hoge.cpp
enum {
AGE,SAGE,GIKO,MONA,
};
template<> void CHoge::InnerAction<AGE>(void) {}
template<> void CHoge::InnerAction<SAGE>(void) {}
template<> void CHoge::InnerAction<GIKO>(void) {}
template<> void CHoge::InnerAction<MONA>(void) {}
typedef void (CHoge::*FUNC)();
FUNC table[] = {
&CHoge::InnerAction<0>,
&CHoge::InnerAction<1>,
&CHoge::InnerAction<2>,
&CHoge::InnerAction<3>
}
void CHoge::Action(void)
{
// 状態ごとに振る舞いを返る。
(this->*table[state_])();
}
こうすると、状態がいくら増えても、変更するのはHoge.cppだけ。
Hoge.hは変えなくてよくなります。プチStateパターンと名付けたけど、
なにげにBridgeパターンも兼ねてるわけです。
tableで「CHoge::InnerAction<0>」とマジックナンバーが入っているのは、
enum順が変わっても、tableの並びを変えなくていい、というテクです。
>>369-423 を参照して下さい。
仕様が不安定な中で開発するときは割と使えると思いますけど、
どうでしょ、このテク。
template<>の中でifは使えないが、三項演算子なら使えるのだな。 誰かこれ使って何かしてくれよ。
>>853 Hoge.hを書き換えられないという状況があんまり想定できん
>>856 Hoge.h を書き換えてビルドしたら、これをインクルードしている
ものも再構築しなければならない罠ってやつでは?
>>857 やればいいやん。ビルドに時間がかかるんならそれはそれで問題。
>>857 外部インターフェースと実装を分離したいなら pimpl イディオム使うのが
一般的だと思う。pimpl イディオムだと、内部的に使うメンバ変数が増えて
も OK だし。
関数レベルのプチな振る舞い変化ならStateパターンなど使わずにswitch/case使うべきと思われ
861 :
デフォルトの名無しさん :02/08/24 09:07
>>849 それ以前に、C++で f(void)はやめれ。間違いじゃないけど。
俺はvoidな変数とvoidな引数がホスィな void set_name_age( char const* name, int age ){} void result = set_name_age( "もな", 5, void, void ); テンプレート使うときに幸せだ・・・
865 :
デフォルトの名無しさん :02/08/24 12:33
>>861 じゃ戻り値intもその時のreturn 0も書くのやめるか?
>>872 Are you a Generic C++ Programmer?
>>872 >867 と >869 は本気で言ってる。それ以前の書き込みは俺じゃないから知らん。
>>866 > じゃ戻り値intもその時のreturn 0も書くのやめるか?
C++ の規格に照らし合わせて
1. 仮引数宣言を (void) とするのは () と等価。
2. 関数の型を省略すると int と見なされる
までは正しいが、
3. int 型関数で return を省略すると、デフォルト値 0 が戻り値として渡される
のは嘘だよな。
省略可能な int, void を書くかどうかはスタイルの問題だが(俺は書くけど)、
return を書かないのは規格上マズイって話。
875 :
デフォルトの名無しさん :02/08/24 17:49
>>874 mainに限ってはreturnがない場合0が返る。
876 :
デフォルトの名無しさん :02/08/24 18:44
// 望洋せんせいは int foo1() { } int foo2( void ) { } int var() { foo1( 0 ); // 問題なし foo2(); // コンパイルエラー } // ってゆってたよ。
ちがった! foo2( 0 ); // これで、コンパイルエラー。 foo2(); // は、もちろんOK。
>>879 いま g++ と gcc で試してみたらそのとおりだった。
スレ汚しちゃってスマソ。
// これも試してみたよ。 // 常に 0 が表示されちゃう。 #include <stdio.h> int foo() {} void main() { printf("%d\n",foo()); } // % g++ -v // gcc version 2.95.3-5 (cygwin special)
>>875 ほんとだ。いつ追加された仕様なんだろうな、これ?
(VC6 あたりだと警告が出る)
883 :
デフォルトの名無しさん :02/08/24 19:22
C99からだったりして
亀レスで失礼。
>>323 "もっと技術的な話をきぼんぬ" って本人にメール出したら多分聞き入れてくれるよ。
...どういった方向の技術の話題を希望するのか書いとけば恵比寿氏も喜ぶよ、きっと。
>>327 いや、恵比寿氏が用意した場所で本人にうざいって言うのは人としてどうかと思うぞ。
わざわざ、人んちに押しかけといて家主に "あんた邪魔、帰れ!" って言うのと同じ様なもんだぞ。
>>884 御説はもっともなのだが、おぬし、流石に亀レスすぎないか。
>>885 ごめん。古い書き込みとはいえ、なんか無駄な非難をほっとけなくて。
ひょっとして本人?
わざわざ名乗らんでもええのに
>>890 気づかれなかったことが、なんか寂しかった。
...スレ汚しスマソ。本題の話を続けてくれ。
じゃ、バイバイ〜♪。(´ω`)ノシ
そんなこと言われても本題と言えるほどのネタがない罠。
893 :
デフォルトの名無しさん :02/09/04 09:59
Lokiがboostに入るなんて話はないんでしょうか?
あったりする。
trickタソ… ハァハァ
>>896 ・Functor, メモリプール, TypeTraits 辺りは既にboostにある。
・TypeListなどはMPL( MetaProgrammingLibrary )とゆーもっと
汎用的な枠組みで吸収。1.30.0くらいでリリース版に入りそう。
・Policyベースのスマートポインタは統合作業&議論中。
・AbstractFactory/Singletoneなどは、boost::DesignPattern
ライブラリを作るとか作らんとか言ってた気がするけど不明。
4compileさん(・∀・)イイ!
901 :
デフォルトの名無しさん :02/09/15 23:14
boostってフリー?商用もいけるの?
ライセンス調べろ
903 :
デフォルトの名無しさん :02/09/15 23:59
キミのこと気持ちよくしてあげたいんだ・・・
904 :
デフォルトの名無しさん :02/09/16 00:12
906 :
デフォルトの名無しさん :02/09/16 00:40
908 :
デフォルトの名無しさん :02/09/16 19:37
>>907 thanks
でも変な訳で意味がよくわからんよ。
誰かやわらかく教えて臭い。
いつの間にか MPL が boost の cvs に入ってますな。
age
age
テンプレートメタプログラミングは戦場では必要なし! っていうスレ立ててもいいっすか・・・・ ;_;
ィィョ
914 :
デフォルトの名無しさん :02/10/04 00:13
ョクナィョ
立てたらi`
>>916 戦場スレに書き込んでみたら一応反応してもらえました。ハァハァ
918 :
デフォルトの名無しさん :02/10/08 00:30
テンプレートで渡された型が、参照(あるいは値)であるかポインタであるかを判断するにはどうしたら いいでしょうか? template<typename T> struct Fn : public std::binary_function< T, T, bool > { result_type operator() ( first_argument_type f, second_argument_type s ) const { return (f.Hoge() < s.Hoge()); } }; のようなファンクタクラスをつくるとき、operator()の内部を f.Hoge() とすべきか f->Hoge() とすべきか コンパイルタイムに判定したいのです。 Lokiのこのへん、とかboostのこれ、とかでいいので情報のポインタをいただけませんか。
>>918 template<typename T> struct Fn : public std::binary_function<T&, T&, bool> {
result_type operator() (T& f, T& s) const {
return (f.Hoge() < s.Hoge());
}
};
template<typename T> struct Fn : public std::binary_function<T*, T*, bool> {
result_type operator() (T* f, T* s) const {
return (f->Hoge() < s->Hoge());
}
};
のように単にオーバーロードすればいいのでは?
920 :
デフォルトの名無しさん :02/10/08 00:46
>>918 template < typename T& >
template < typename T* >で判断できなかったかな?
どうだったっけ?
921 :
デフォルトの名無しさん :02/10/08 00:48
>>921 template<typename T> struct Fn : public std::binary_function<std::auto_ptr<T>, std::auto_ptr<T>, bool> {
result_type operator() (std::auto_ptr<T> f, std::auto_ptr<T> s) const {
return (f->Hoge() < s->Hoge());
}
};
ではいかんの?
Modernの2.10型の特性(TypeTraits)か?
>>920 template <class T> class A;
template <class T> class A<T*>{};
template <class T> class A<T&>{};
こうか?
>>919 オーバーロードできるんですか。理解が足りませんでした。
てっきりboost::mplのようなものを使って判断するとばっかり。
>>922 スマートポインタの類は恥ずかしながら一度も使ったことが
ありません。auto_ptrの引数で受ける、というのがどういう
意味を持ちどういう動作をするのか、勉強してみます。
ありがとうございました>919,922他の神々
>>922 いいんですが、巷にはたくさんスマートポインタがあり、
対応するのにいちいちそれを書いていたらとっても大変です。
以下のクラスを書きました。
参照、ポインタ、スマートポインタを吸収し、ただのポインタとして保持します。
template <typename T>
class pointer
{
public:
template <class U>pointer(U &p) { init(p,&p); }
pointer(T &p) { p_=&p; }
pointer(T *p) { p_=p; }
operator T *() const { return p_; }
T *operator ->() const { return p_; }
private:
template <class U> void init(U &p,const T *) { p_=&p; }
template <class U> void init(U &p,const void *) { p_=&*p; }
private:
T *p_;
};
続き 使い方は template<typename T> struct Fn : public std::binary_function<pointer<T>, pointer<T>, bool> { result_type operator() (pointer<T> f, pointer<T> s) const { return (f->Hoge() < s->Hoge()); } }; これひとつで参照、ポインタ、スマートポインタを渡せる関数オブジェクトになります。
あーこりゃべんりですね。ども。
>>925 *での間接参照を許さないスマートポインタもあったりするからちょとやっかいだな。
# auto_ptr もじゃなかったっけ?(うろ覚えスマソ)
>>929 &pは許さないスマートポインタはたくさんありますが、
*pを許さない奴はめったにありません。(auto_ptrもOKです)。
これはMyライブラリーに入っていて良く使うので何が悪いか良くわかってます。
欠点はpointer<void>と出来ないことです。
ですので、pointer<void>の時の特殊化も定義してください。
あと、constポインタにしたい場合はpointer<const int> としてください。
あ、すいません。 T &operator *() const { return *p_; } をpublic面罵に追加してください。なぜかなかったです。
>>930 ゴメンよ、どっか見間違えてたよ
生ポインタへの変換を許さないのはあるけど*が駄目なのは滅多に無いね
うわわわ、いろいろやってみていたら、関数オブジェクトは同名の オーバーロードをするとエラーが出ますよ。
>>934 Borland-C++ 5.6です。今からMinGW(gcc3.2)でも試してみます。
MinGW(gcc3.2)でもやはり redifinitionエラーが出ます。同名の関数オブジェクト は使えないなんて初めて知った(汗。
>>926 参照を渡すときのFnの実体化は、Fn<Foo> f; ですか Fn<Foo&> f; ですか?
とりあえず後者は通らないようです(gcc3.2)
いや、pointer<>は T* を保持するんだから、Tは * やら & つけちゃだめか。 スマソ。
できました。サンクスコ。 禿げしくコンパイル時間が延びたような気もするが・・
うぅぅ〜。。。typedefのtemplateはダメなのかよぉ…。
template <template<class> class T>なクラス←なんて言うんだ? を書いてみたものの、bccだと型変換演算子でコケて、 gccだとstd::vectorで特殊化した方のクラスの演算子でコケる…。。。 (−_−) (∩ ∩)
943 :
デフォルトの名無しさん :02/10/10 13:13
http://sourceforge.net/projects/loki-lib/ ここから落とした最新のLoki+テストコードを使っています。
コンパイラはg++3.2です。
Loki/tools/RegressionTest/Test_MultiMethods.cpp
このテストプログラムにおいてよく分からないことが
あるので教えてください。
場所はBasicDispatcherをテストしている160行目あたりの
ShapeDispatcherAddというテンプレート関数です。
ここで関数の引数として取得したディスパッチャーインスタンスの
Addテンプレート関数を呼んでいるのですが、
この関数のテンプレートパラメータはどこで指定すれば
よいのでしょうか?。テストコードでは(通常の関数テンプレートと
同じように)メソッドをコールする時点において指定していますが
どうもこれが上手くいっていないようです。
x.Add<Shape1,Shape2>(HatchDispatcher<Shape1,Shape2>);
という行で、既にインスタンス化されたテンプレートクラス内の
関数を実体化するはずなのですが、これがコンパイラエラーと
なります。
x.Add()(HatchDispatcher<Shape1,Shape2>);とテンプレートパラメータ
の指定を取り除くとエラーは消えます。
なにか問題を回避するような方法があれば教えてください。
訂正です x.Add()(HatchDispatcher<Shape1,Shape2>); ではなくて x.Add(HatchDispatcher<Shape1,Shape2>); でした
945 :
デフォルトの名無しさん :02/10/10 14:14
>>941 どんなのが駄目なの?
いま漏れも
typedef boost::tuple<const int, const std::string, const std::string> hoge;
がVCでのみ通らなくて困ってるんだけど。
#スレ違いの予感
エラーの原因を突き止めるため単純化したプログラムを 一つ作ってみました。 template<class T> class CLS{ public: template<class U> void memfunc(){U i;} }; template<class T> void func(T& a){ a.memfunc<int>(); //これがどうもおかしい } int main(){ CLS<int> a; func(a); } これを回避するためにはどうすればいいのでしょう? template<class T> class CLS{ public: template<class U> void memfunc(){U i;} }; int main(){ CLS<int> a; a.memfunc<int>(); } このようにパラメータとしてやり取りするのを省けば 上手くいくのですが。。。
>>942 g++ でダメな演算子ってどんなの?
まあ、なんにしても VC++ じゃ通らないから仕事では
避けざるをえないんだけどね。
やっぱり仕様書をよく覚えないとダメだね、こりゃ。 いままで仕様書見てプログラミング言語覚えたこと なかったからどうも抵抗があったんだけどそうも いってられなさそう。。。 14882の14章をよく読んできます。
>>946 これは、template 限定子ってのが必要になるケースだね。
template<class T>
void func(T& a) { // ここでは a がどういう型か分からないので
a.template memfunc<int>(); // このように memfunc がテンプレートであることを明示する
}
これで 950 レス目だけど、次スレはもう不要でしょ。 とりあえずは STL スレか Boost スレを使うことにして、 いずれは 「C++ Template & Libraries (STL, Boost, Loki, etc.)」 みたいな形で統一しましょう。
>>949 素晴らしい!素晴らしすぎます!!!
どうもありがとうございました。
どうしてそんなことを知っているのでしょうか?
"C++""限定子"で検索かけても一つ引っかかるだけ。。。
C++は奥が深いですね。
ちなみにテストコードは以下のようになりました。
template<class T> class CLS{
public:
template<class U>
void memfunc(U&){U i;}
};
template<class T>
void func(T& a){
// a.template memfunc(a); //テンプレート関数の型推論を試すその2。error
a.template memfunc<T>(a);
}
int main(){
CLS<int> a;
func(a); //テンプレート関数の型推論を試すその1。ok
}
型推論の機構もあわせてもう少し調べてみます。
ありがとうございました。
>>951 Borland-C++5.5.1だとtemplate限定子がなくても通ってしまうね。
でもgcc3.2だとエラーが出る。
プログラミング言語C++第3版§C.13.6、P971によるとmemfuncの
テンプレート引数は予測不能なので、"<"が比較演算子だと誤認
されエラーが出るようだ。
>>952 プログラミング言語C++はそんなことまで載って
いるんですね。私はC++Primerで勉強しているのですが
そんな記述あったかしら??。帰って読み直してみます。
ちなみにCLSはpublicのメンバーしかないから
structとすべきですね。こういう細かなルールは
大事にしたいものです。。
>>950 次スレは要らないでしょうね。Lokiはもう一般的に
認知されたと思っていますので、特別に扱うのも
なにか違うかなとおもいます。
boostスレで十分でしょう。ちなみに私の質問は
相談室の方ですべきでした。すみませんm( )m
Lokiのダブルディスパッチャ(<Loki/MultiMethods.h>)に関して 疑問があります。 class FnDispatcherなのですが、このクラスは三つのAdd()関数を 持っていますが引数のないAddが二つ含まれています。 これってオーバーロードできずにコンパイルエラーになると 思うのですがどうでしょうか? 一つは対照ディスパッチャ(二つの要素の順序関係なし)として 機能するようにbool型のフラグ(bool symmetric)を受け付けるように 定義されていますが、そもそも関数の部分的特殊化は出来ないはずですよね? これはg++-3.2では"cannot be overloaded"というエラーが出ます。 これはコンパイラの構文解釈としては正しいと思われますが、 なぜかg++-2.95では通ってしまうんですね。。 ライブラリのバグでしょうか?それとも私の何勘違いでしょうか?
また、正しくオーバーロードが行われるように、 対照ディスパッチャの引数としてAdd(bool)などという ものを加えれば正しく動作するのですが、これって なんかカッコ悪いですよね。汗 コンパイル時にだけしか使わない情報はなるべくテンプレート パラメータとして渡したいところです。 template <class SomeLhs, class SomeRhs, ResultType (*callback)(SomeLhs&, SomeRhs&), bool symmetric> void Add() { typedef Private::FnDispatcherHelper< BaseLhs, BaseRhs, SomeLhs, SomeRhs, ResultType, CastingPolicy<SomeLhs,BaseLhs>, CastingPolicy<SomeRhs,BaseRhs>, callback> Local; Add<SomeLhs, SomeRhs>(&Local::Trampoline); if (symmetric) { Add<SomeRhs, SomeLhs>(&Local::TrampolineR); } }
そもそも対照性を持つ場合はこのようなコードになっているので、 単にAddのテンプレート引数symmetricにデフォルト値として falseを与えればいいように思うのですが、それだと困るような コンパイラがあるのでしょうか? template <class SomeLhs, class SomeRhs, ResultType (*callback)(SomeLhs&, SomeRhs&), bool symmetric = false> void Add()
Loki のことは全くわからないんだけど、関数の部分的特殊化は 可能のはず。VC++ みたいにできないコンパイラもあるけど。 >956 関数テンプレートでは、デフォルトのテンプレート引数は使えないはず。
あ、勘違いしてました。。。恥
FnDispatcher::Add()は部分的特殊化ではなくて、
一次テンプレートが二つあるんですね。
んー、そうするとAddが二つあるのはいいんだろうか?
>>957 ModernC++DesignのP30には
「残念なことに、テンプレートの部分的特殊化は、メンバ関数、
非メンバ関数を問わず、関数には適用されません。」と書いてあります。
例として、
template <class T, class U> T Fun(U obj); //一次テンプレート
template <class U> void Fun(U obj); //部分的な特殊化(不正)
template <class T> T Fun(Window obj); //オーバーロード(正当)
というものが挙げられています。
関数テンプレートのデフォルト引数には関しては、、、調べてみます。
template <class U> void Fun(U obj); //部分的な特殊化(不正) この行は間違いでした。書きたかったのは、 template <class U> void Fun<void, U>(U obj); //部分的な特殊化(不正) です。失礼しました。
あ、おそかったかw すまん、関数テンプレートの部分特殊化はダメだったかもしれない。 多重定義は可能なので部分特殊化ができていると勘違いした。
毎度、スレ汚しすみませんが簡単なテストプログラムです。 #include<iostream> template <class T> struct CLS { template <class U, class R> void Add(){std::cout << "二つのテンプレートパラメータの関数" << std::endl;} template <class U> void Add(){std::cout << "一つのテンプレートパラメータの関数" << std::endl;} }; int main(){ CLS<int> a; a.Add<int, int>(); a.Add<int>(); } これがg++-2.95だと通ってしまうんですね。g++-3.2によるエラーは以下の通りです。 test2.cc:8: `template<class U> void CLS::Add() [with U = U, T = int]' and ` template<class U, class R> void CLS::Add() [with U = U, R = R, T = int]' cannot be overloaded そもそも一次テンプレートを二つも定義できてしまうのはやはり問題で、 それに増して、テンプレート引数の数による部分的特殊化が出来てしまうのは ちょっと。。。動作としてはg++-3.2の動作が正しいと思うのですがどうでしょうか? また、もしそうだとするならこれはLokiのバグですよね?
>>957 さん
何か資料に当たったわけではないのですが、
テンプレート関数のテンプレートパラメータには
デフォルト引数は設定できないです。
g++の3.2,2.95のどちらも
"default argument for template parameter"
と返してきます。
勉強になりました。ありがとうございます。
ちょっと気になったので、規格書を調べてみた。 ●関数の部分的特殊化は不可 14章冒頭の2 a function template declaration, the declarator-id shall be a template-name (i.e., not a template-id). つまり、template<class T> void foo<T>(); のように <T> を付けた宣言は できないということ。(ただし explicit specialization の場合は可) ●関数テンプレートではデフォルトのテンプレート引数を使えない 14.1 の 9 A default template-argument shall not be specified in a function template declaration or a function template definition, nor in the template-parameter-list of the definition of a member of a class template. ●テンプレート引数が異なっていれば、戻値やシグネチャの一致する関数テンプレートの オーバーロードは可能 14.5.5.1 の 4 The signature of a function template consists of its function signature, its return type and its template parameter list. The names of the template parameters are significant only for establishing the relationship between the template parameters and the rest of the signature. [Note: two distinct function templates may have identical function return types and function parameter lists, even if overload resolution alone cannot distinguish them. template<class T> void f(); template<int I> void f(); // OK: overloads the first template // distinguishable with an explicit template argument list 実際、g++-3.2 でも非メンバ関数テンプレートならオーバーロード可能だった。
なるほど、どうもありがとうございます。 とくに三つ目の件に関しては勉強になりましたm( )m ●1つ目 explicit specializationとは完全な特殊化という意味ですよね? template <class T> T foo(); template <> int foo<int>(){}; template <> double foo<double>(){}; というような。。 ●3つ目 以下のようなコードはg++-3.2,2.95どちらでもOKでした。 namespace{//無名名前空間の外でも同じでした。 template<class T> void func(){cout << "<class T>" << endl;} template<int I> void func(){cout << "<int I>" << endl;} template<class T,class U> void func(){cout << "<class T,class U>" << endl;} template<class T,int I> void func(){cout << "<class T,class int>" << endl;} } int main(){ func<int>(); func<8>(); func<int,char>(); func<int,3>(); } ということはg++-3.2のテンプレートメンバ関数の解釈はどうなんでしょう? g++のバグということになるんでしょうかね??
補足ですが、クラスに関して同じようなことは当然×みたいですね。 struct CLS; template <class T> struct CLS; template <class T, class U> struct CLS; こういうのは当然のごとくエラーになりますね。 previous declaration `template <class T> CLS<T>'といったかんじのメッセージがでます。 関数テンプレートが部分的特殊化が許されていない分、ユーザーに対して サービスしてくれたのかな(藁 というよりも考え方としてはオーバーロードの延長として見るべきでしょうかね。 クラスは原則として名前が一意に決定されていなくてはならない。だけどそれでは コンパイル時にクラスの選択をさせることができない。原則を守りつつの追加という形で explicit specialization, partical specializationがそれぞれ可能になっている。 関数にはもとからオーバーロード機能が付いていたので、その機能を補う形で 一次テンプレート(というよりも関数テンプレートには一次しかない。完全な特殊化は どちらかというと実体化っていうかんじかな)でのオーバーロードと explicit specializationの二つの機能が付いたという。。。 C++を勉強していていつも思うのが、なんでそういう仕様になっているのかという その理由の分からなさのこと。どういった事情からそういう仕様になっているのか まとめてあるようなドキュメントが読みたいです、というよりその前に英語の仕様書を なんとか読まなくてはいけないのですが。。。はぁー
>949 いいことしった(・∀・)!
967 :
デフォルトの名無しさん :02/10/20 17:15
アリガトウ-
971 :
デフォルトの名無しさん :02/10/20 18:29
>>968 これ売り物?
ダンロードできないんですが。
コンパイラのバックエンドを作成している企業にしか販売してませーん ということじゃないかなぁ。
ありがとう。 やっぱ売り物なのね。
http://www.edg.com/faq.html > Q: How much does a source code license cost?
>
> A: Usually somewhere between $40,000 and $250,000. There are
> lots of different kinds of licenses, so you'll have to contact us
> to get a specific quote.
ちょっと個人では手が出しにくいお値段だぁね。
gcc3.2でいいやぁ・・
VCに使えばいいのに
>>977 このスレではVCは出入り禁止ですが何か・・・・?
梅梅
980ゲット
981 :
デフォルトの名無しさん :02/10/28 18:51
このスレも埋め立てるだけか。
C++スレは少し減らした方がいいと思われ。
記念パピコV(^o^)V
という訳でLokiネタもboostスレへと殴りこみに入ります。 みなさん一年間どうもありがとうございました。
梅うまうま